mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
perf(nuxt): avoid multiple calls to getCachedData
(#28472)
This commit is contained in:
parent
9397def672
commit
b13582205a
@ -252,18 +252,17 @@ export function useAsyncData<
|
|||||||
console.warn('[nuxt] `boolean` values are deprecated for the `dedupe` option of `useAsyncData` and will be removed in the future. Use \'cancel\' or \'defer\' instead.')
|
console.warn('[nuxt] `boolean` values are deprecated for the `dedupe` option of `useAsyncData` and will be removed in the future. Use \'cancel\' or \'defer\' instead.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make more precise when v4 lands
|
|
||||||
const hasCachedData = () => options.getCachedData!(key, nuxtApp) != null
|
|
||||||
|
|
||||||
// Create or use a shared asyncData entity
|
// Create or use a shared asyncData entity
|
||||||
|
const initialCachedData = options.getCachedData!(key, nuxtApp)
|
||||||
|
const hasCachedData = initialCachedData != null
|
||||||
|
|
||||||
if (!nuxtApp._asyncData[key] || !options.immediate) {
|
if (!nuxtApp._asyncData[key] || !options.immediate) {
|
||||||
nuxtApp.payload._errors[key] ??= asyncDataDefaults.errorValue
|
nuxtApp.payload._errors[key] ??= asyncDataDefaults.errorValue
|
||||||
|
|
||||||
const _ref = options.deep ? ref : shallowRef
|
const _ref = options.deep ? ref : shallowRef
|
||||||
|
|
||||||
nuxtApp._asyncData[key] = {
|
nuxtApp._asyncData[key] = {
|
||||||
data: _ref(options.getCachedData!(key, nuxtApp) ?? options.default!()),
|
data: _ref(hasCachedData ? initialCachedData : options.default!()),
|
||||||
pending: ref(!hasCachedData()),
|
pending: ref(!hasCachedData),
|
||||||
error: toRef(nuxtApp.payload._errors, key),
|
error: toRef(nuxtApp.payload._errors, key),
|
||||||
status: ref('idle'),
|
status: ref('idle'),
|
||||||
_default: options.default!,
|
_default: options.default!,
|
||||||
@ -285,8 +284,11 @@ export function useAsyncData<
|
|||||||
(nuxtApp._asyncDataPromises[key] as any).cancelled = true
|
(nuxtApp._asyncDataPromises[key] as any).cancelled = true
|
||||||
}
|
}
|
||||||
// Avoid fetching same key that is already fetched
|
// Avoid fetching same key that is already fetched
|
||||||
if ((opts._initial || (nuxtApp.isHydrating && opts._initial !== false)) && hasCachedData()) {
|
if ((opts._initial || (nuxtApp.isHydrating && opts._initial !== false))) {
|
||||||
return Promise.resolve(options.getCachedData!(key, nuxtApp))
|
const cachedData = opts._initial ? initialCachedData : options.getCachedData!(key, nuxtApp)
|
||||||
|
if (cachedData != null) {
|
||||||
|
return Promise.resolve(cachedData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
asyncData.pending.value = true
|
asyncData.pending.value = true
|
||||||
asyncData.status.value = 'pending'
|
asyncData.status.value = 'pending'
|
||||||
@ -375,7 +377,7 @@ export function useAsyncData<
|
|||||||
onUnmounted(() => cbs.splice(0, cbs.length))
|
onUnmounted(() => cbs.splice(0, cbs.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchOnServer && nuxtApp.isHydrating && (asyncData.error.value || hasCachedData())) {
|
if (fetchOnServer && nuxtApp.isHydrating && (asyncData.error.value || initialCachedData != null)) {
|
||||||
// 1. Hydration (server: true): no fetch
|
// 1. Hydration (server: true): no fetch
|
||||||
asyncData.pending.value = false
|
asyncData.pending.value = false
|
||||||
asyncData.status.value = asyncData.error.value ? 'error' : 'success'
|
asyncData.status.value = asyncData.error.value ? 'error' : 'success'
|
||||||
|
@ -227,6 +227,17 @@ describe('useAsyncData', () => {
|
|||||||
`)
|
`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should only call getCachedData once', async () => {
|
||||||
|
const getCachedData = vi.fn(() => ({ val: false }))
|
||||||
|
const { data } = await useAsyncData(() => Promise.resolve({ val: true }), { getCachedData })
|
||||||
|
expect(data.value).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"val": false,
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
expect(getCachedData).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
it('should use default while pending', async () => {
|
it('should use default while pending', async () => {
|
||||||
const promise = useAsyncData(() => Promise.resolve('test'), { default: () => 'default' })
|
const promise = useAsyncData(() => Promise.resolve('test'), { default: () => 'default' })
|
||||||
const { data, pending } = promise
|
const { data, pending } = promise
|
||||||
|
Loading…
Reference in New Issue
Block a user