Skip to content

Commit

Permalink
fix(nuxt): wrap caught asyncData error in createError (#24093)
Browse files Browse the repository at this point in the history
Co-authored-by: Bogdan Kostyuk <contact@bogdankostyuk.xyz>
  • Loading branch information
2 people authored and manniL committed Dec 11, 2023
1 parent 30978c3 commit d324bdd
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
11 changes: 5 additions & 6 deletions packages/nuxt/src/app/composables/asyncData.ts
Expand Up @@ -204,6 +204,9 @@ export function useAsyncData<
if (options.pick) {
result = pick(result as any, options.pick) as DataT
}

nuxt.payload.data[key] = result

asyncData.data.value = result
asyncData.error.value = null
asyncData.status.value = 'success'
Expand All @@ -212,19 +215,15 @@ export function useAsyncData<
// If this request is cancelled, resolve to the latest request.
if ((promise as any).cancelled) { return nuxt._asyncDataPromises[key] }

asyncData.error.value = error
asyncData.error.value = createError(error) as DataE
asyncData.data.value = unref(options.default!())
asyncData.status.value = 'error'
})
.finally(() => {
if ((promise as any).cancelled) { return }

asyncData.pending.value = false
nuxt.payload.data[key] = asyncData.data.value
if (asyncData.error.value) {
// We use `createError` and its .toJSON() property to normalize the error
nuxt.payload._errors[key] = createError(asyncData.error.value)
}

delete nuxt._asyncDataPromises[key]
})
nuxt._asyncDataPromises[key] = promise
Expand Down
28 changes: 27 additions & 1 deletion test/nuxt/composables.test.ts
Expand Up @@ -128,10 +128,20 @@ describe('useAsyncData', () => {
})

it('should capture errors', async () => {
const { error, status, pending } = await useAsyncData(() => Promise.reject(new Error('test')))
const { data, error, status, pending } = await useAsyncData('error-test', () => Promise.reject(new Error('test')), { default: () => 'default' })
expect(data.value).toMatchInlineSnapshot('"default"')
expect(error.value).toMatchInlineSnapshot('[Error: test]')
expect(status.value).toBe('error')
expect(pending.value).toBe(false)
expect(useNuxtApp().payload._errors['error-test']).toMatchInlineSnapshot('[Error: test]')

// TODO: fix the below
// const { data: syncedData, error: syncedError, status: syncedStatus, pending: syncedPending } = await useAsyncData('error-test', () => ({}), { immediate: false })

// expect(syncedData.value).toEqual(null)
// expect(syncedError.value).toEqual(error.value)
// expect(syncedStatus.value).toEqual('idle')
// expect(syncedPending.value).toEqual(true)
})

// https://github.com/nuxt/nuxt/issues/23411
Expand Down Expand Up @@ -182,6 +192,22 @@ describe('useAsyncData', () => {
}
`)
})

it('should use default while pending', async () => {
const promise = useAsyncData(() => Promise.resolve('test'), { default: () => 'default' })
const { data, pending } = promise

expect(pending.value).toBe(true)
expect(data.value).toMatchInlineSnapshot('"default"')

await promise
expect(data.value).toMatchInlineSnapshot('"test"')
})

it('should use default after reject', async () => {
const { data } = await useAsyncData(() => Promise.reject(new Error('test')), { default: () => 'default' })
expect(data.value).toMatchInlineSnapshot('"default"')
})
})

describe('errors', () => {
Expand Down

0 comments on commit d324bdd

Please sign in to comment.