Skip to content

Commit c4a8481

Browse files
committed
fix: sync watch request in useAsyncData #33189
1 parent b9ec650 commit c4a8481

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

packages/nuxt/src/app/composables/asyncData.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ export function useAsyncData<
322322

323323
// setup watchers/instance
324324
const hasScope = getCurrentScope()
325-
const unsubExecute = watch([key, ...(options.watch || [])], ([newKey], [oldKey]) => {
325+
const unsubKeyWatcher = watch(key, (newKey, oldKey) => {
326326
if ((newKey || oldKey) && newKey !== oldKey) {
327327
const hasRun = nuxtApp._asyncData[oldKey]?.data.value !== undefined
328328
const isRunning = nuxtApp._asyncDataPromises[oldKey] !== undefined
@@ -345,14 +345,19 @@ export function useAsyncData<
345345
if (options.immediate || hasRun || isRunning) {
346346
nuxtApp._asyncData[newKey].execute(initialFetchOptions)
347347
}
348-
} else {
349-
asyncData._execute({ cause: 'watch', dedupe: options.dedupe })
350348
}
351349
}, { flush: 'sync' })
352350

351+
const unsubWatcher = options.watch
352+
? watch(options.watch, () => {
353+
asyncData._execute({ cause: 'watch', dedupe: options.dedupe })
354+
})
355+
: () => {}
356+
353357
if (hasScope) {
354358
onScopeDispose(() => {
355-
unsubExecute()
359+
unsubKeyWatcher()
360+
unsubWatcher()
356361
unregister(key.value)
357362
})
358363
}

test/nuxt/use-async-data.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,55 @@ describe('useAsyncData', () => {
356356
expect(promiseFn).toHaveBeenCalledTimes(1)
357357
})
358358

359+
it('should watch params deeply in a non synchronous way', async () => {
360+
const foo = ref('foo')
361+
const baz = ref('baz')
362+
const locale = ref('en')
363+
const params = reactive({ deep: { baz: 'baz' } })
364+
const requestHistory = reactive([])
365+
watch(foo, (foo) => {
366+
params.foo = foo
367+
params.locale = locale.value
368+
}, { immediate: true })
369+
watch(baz, (baz) => {
370+
params.deep.baz = baz
371+
}, { immediate: true })
372+
await useAsyncData(uniqueKey, async () => {
373+
requestHistory.push(JSON.parse(JSON.stringify(params)))
374+
await promiseFn()
375+
}, { watch: params })
376+
foo.value = 'bar'
377+
locale.value = 'fr'
378+
// We need to wait for the debounce 0
379+
await (new Promise(resolve => setTimeout(resolve, 5)))
380+
baz.value = 'bar'
381+
await nextTick()
382+
383+
expect(requestHistory).toEqual([
384+
{
385+
deep: {
386+
baz: 'baz',
387+
},
388+
foo: 'foo',
389+
locale: 'en',
390+
},
391+
{
392+
deep: {
393+
baz: 'baz',
394+
},
395+
foo: 'bar',
396+
locale: 'fr',
397+
},
398+
{
399+
deep: {
400+
baz: 'bar',
401+
},
402+
foo: 'bar',
403+
locale: 'fr',
404+
},
405+
])
406+
})
407+
359408
it('should execute the promise function multiple times when dedupe option is not specified for multiple calls', () => {
360409
const promiseFn = vi.fn(() => Promise.resolve('test'))
361410
useAsyncData(uniqueKey, promiseFn)

0 commit comments

Comments
 (0)