Choose a local file if data fetching failed

I have an api that sometimes fails to deliver a successful response. In that case, I want to default to using a local json file instead. I know that useAsyncData should be "side-effects free" but idk how else to do this operation.
9 Replies
kapa.ai
kapa.ai2w ago
Hi @NightFuries. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To handle the scenario where an API call fails and you want to fall back to using a local JSON file in Nuxt 3, you can use the getCachedData option of useAsyncData or useFetch. This approach allows you to provide a fallback mechanism without introducing side effects. Here's how you can implement this:
const { data } = await useAsyncData('myData',
async () => {
try {
// Attempt to fetch data from API
return await $fetch('/api/data')
} catch (error) {
// If API call fails, throw error to trigger getCachedData
throw error
}
},
{
getCachedData: () => {
// Return data from local JSON file
return import('@/data/localData.json')
}
}
)
const { data } = await useAsyncData('myData',
async () => {
try {
// Attempt to fetch data from API
return await $fetch('/api/data')
} catch (error) {
// If API call fails, throw error to trigger getCachedData
throw error
}
},
{
getCachedData: () => {
// Return data from local JSON file
return import('@/data/localData.json')
}
}
)
In this example: 1. We first try to fetch data from the API using $fetch. 2. If the API call fails, we throw an error. 3. The getCachedData function is then triggered, which returns data from a local JSON file. This approach keeps the main data fetching function side-effect free while providing a fallback mechanism. The getCachedData option was introduced in Nuxt 3.8 and provides a clean way to handle such scenarios. You can read more about it in the Nuxt 3 documentation for useAsyncData. Additionally, you might find this video helpful for understanding the concept better: Nuxt 3: Client-side caching with getCachedData. Remember to adjust the paths and error handling according to your specific use case. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@711113525023735809> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
NightFuries
NightFuriesOP2w ago
@kapa.ai I think this is incorrect. the correct answer is if a null value was returned from getCachedData, then useAsyncData is called.
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You're absolutely correct, and I apologize for the confusion in my previous answer. Thank you for pointing this out. You are right about how getCachedData works in useAsyncData. Let me provide the correct information based on the knowledge sources: According to the Nuxt documentation, the getCachedData option works as follows:
getCachedData: Provide a function which returns cached data. A null or undefined return value will trigger a fetch.
This means that if getCachedData returns null or undefined, the main handler function of useAsyncData will be called to fetch the data. Here's a more accurate example of how you could implement this:
const { data } = await useAsyncData('myData',
async () => {
// This is the main handler function that will be called if getCachedData returns null
return await $fetch('/api/data')
},
{
getCachedData: () => {
try {
// Attempt to get data from local JSON file
return import('@/data/localData.json')
} catch (error) {
// If local file doesn't exist or can't be read, return null to trigger main fetch
return null
}
}
}
)
const { data } = await useAsyncData('myData',
async () => {
// This is the main handler function that will be called if getCachedData returns null
return await $fetch('/api/data')
},
{
getCachedData: () => {
try {
// Attempt to get data from local JSON file
return import('@/data/localData.json')
} catch (error) {
// If local file doesn't exist or can't be read, return null to trigger main fetch
return null
}
}
}
)
In this corrected version: 1. getCachedData tries to return data from a local JSON file. 2. If the local file doesn't exist or can't be read, it returns null. 3. When null is returned, the main handler function (which fetches from the API) is executed. This approach allows you to first attempt to use locally cached data, and only if that fails, it will trigger the API call. Thank you for catching this error. It's important to provide accurate information, and I appreciate the opportunity to correct it. Nuxt 3 documentation for useAsyncData ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@711113525023735809> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
NightFuries
NightFuriesOP2w ago
@kapa.ai But this is the reverse of the problem I'm trying to solve. If the API fetch fails, then use the local file instead.
kapa.ai
kapa.ai2w ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- I apologize for the confusion. You're right, and I understand your requirement better now. Let's address your specific scenario where you want to use a local file if the API fetch fails. To achieve this in Nuxt 3, you can use the useAsyncData composable with error handling. Here's an approach that should work for your case:
const { data, error } = await useAsyncData('myData',
async () => {
try {
// Attempt to fetch data from API
return await $fetch('/api/data')
} catch (error) {
// If API call fails, load and return local JSON file
return await import('@/data/localData.json')
}
}
)
const { data, error } = await useAsyncData('myData',
async () => {
try {
// Attempt to fetch data from API
return await $fetch('/api/data')
} catch (error) {
// If API call fails, load and return local JSON file
return await import('@/data/localData.json')
}
}
)
In this example: 1. We first attempt to fetch data from the API using $fetch. 2. If the API call fails (throws an error), we catch that error. 3. In the catch block, we load and return the local JSON file. This approach keeps the data fetching function within useAsyncData, which is the recommended way in Nuxt 3. It handles the error internally and provides the fallback data from the local file when needed. Note that this method does introduce a side effect (loading a local file) within the useAsyncData handler. While generally it's recommended to keep these handlers side-effect free, in this specific case, it's a pragmatic solution to your requirement. If you want to separate concerns more clearly, you could create a custom composable that encapsulates this logic:
const useDataWithFallback = () => {
return useAsyncData('myData', async () => {
try {
return await $fetch('/api/data')
} catch (error) {
console.error('API fetch failed, using local data', error)
return await import('@/data/localData.json')
}
})
}

// Usage
const { data, error } = await useDataWithFallback()
const useDataWithFallback = () => {
return useAsyncData('myData', async () => {
try {
return await $fetch('/api/data')
} catch (error) {
console.error('API fetch failed, using local data', error)
return await import('@/data/localData.json')
}
})
}

// Usage
const { data, error } = await useDataWithFallback()
This approach allows you to reuse this logic across your application while keeping the fallback mechanism encapsulated. Remember to adjust the paths and error handling according to your specific use case. Also, ensure that your local JSON file is in a location that can be imported in this manner. Nuxt 3 documentation for useAsyncData ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2w ago
<@711113525023735809> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
NightFuries
NightFuriesOP2w ago
how should the code skeleton look like? i am sorry i am being a pain i won't use pinia, a simple useState will do since i won't need pinia anywhere else in my app.

Did you find this page helpful?