question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

When two useAsyncData with same key refresh at same time, only one of them updates.

See original GitHub issue

Environment

  • Operating System: Darwin
  • Node Version: v14.18.2
  • Nuxt Version: 3.0.0-rc.3
  • Package Manager: npm@6.14.17
  • Builder: vite
  • User Config: typescript, publicRuntimeConfig, buildModules, alias, vite
  • Runtime Modules: -
  • Build Modules: @pinia/nuxt@0.1.9

Reproduction

Simple demostrate

let i = 0;
const fetch = () => {
  console.log('load');
  return new Promise((resolve) => setTimeout(() => resolve(i++), 100));
};

const getData = () => useAsyncData('requestKey', fetch);

const a = await getData();
const b = await getData();

const refresh = () => {
  a.refresh();
  b.refresh();
};

Full https://stackblitz.com/edit/github-ymf7zt?file=app.vue Click the refresh button

Describe the bug

The cache of useAsyncData errornously cache the part that apply change to data container. Results in the second use refresh completely ignored.

https://github.com/nuxt/framework/blob/ad420238b1e7635e18f6f8cecef868cd2d83e8b3/packages/nuxt/src/app/composables/asyncData.ts#L115-L134

These lines are not supposed to be cached, because the asyncData is not guranteed to be the same instance even key is the same.

Additional context

My temporay patch
diff --git a/node_modules/nuxt/dist/app/composables/asyncData.mjs b/node_modules/nuxt/dist/app/composables/asyncData.mjs
index 3b49030..eb29161 100644
--- a/node_modules/nuxt/dist/app/composables/asyncData.mjs
+++ b/node_modules/nuxt/dist/app/composables/asyncData.mjs
@@ -35,15 +35,21 @@ export function useAsyncData(key, handler, options = {}) {
     pending: ref(!useInitialCache()),
     error: ref(nuxt.payload._errors[key] ?? null)
   };
+  let localDataPromise
   asyncData.refresh = (opts = {}) => {
+    let dataPromise
     if (nuxt._asyncDataPromises[key]) {
-      return nuxt._asyncDataPromises[key];
+      dataPromise = nuxt._asyncDataPromises[key];
     }
     if (opts._initial && useInitialCache()) {
       return nuxt.payload.data[key];
     }
     asyncData.pending.value = true;
-    nuxt._asyncDataPromises[key] = Promise.resolve(handler(nuxt)).then((result) => {
+    if (dataPromise == null) {
+      dataPromise = Promise.resolve(handler(nuxt))
+      nuxt._asyncDataPromises[key] = dataPromise
+    }
+    localDataPromise = dataPromise.then((result) => {
       if (options.transform) {
         result = options.transform(result);
       }
@@ -63,7 +69,7 @@ export function useAsyncData(key, handler, options = {}) {
       }
       delete nuxt._asyncDataPromises[key];
     });
-    return nuxt._asyncDataPromises[key];
+    return localDataPromise
   };
   const initialFetch = () => asyncData.refresh({ _initial: true });
   const fetchOnServer = options.server !== false && nuxt.payload.serverRendered;
@@ -91,7 +97,7 @@ export function useAsyncData(key, handler, options = {}) {
       onUnmounted(off);
     }
   }
-  const asyncDataPromise = Promise.resolve(nuxt._asyncDataPromises[key]).then(() => asyncData);
+  const asyncDataPromise = Promise.resolve(localDataPromise).catch(() => {}).then(() => asyncData);
   Object.assign(asyncDataPromise, asyncData);
   return asyncDataPromise;
 }

Cache the handler(nuxt) but always apply the rest

Logs

No response

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mmis1000commented, Sep 6, 2022

It seems this issue need to be revisited due to change in RC9.

Due to following change. https://github.com/nuxt/framework/pull/7055 This issue seems to be no longer reproducible.

1reaction
johannesstrickercommented, Jul 6, 2022

I just came across this behaviour, because my second call to refresh() wasn’t fetching new data. I thought I was using useAsyncData incorrectly, but after looking through it’s implementation I realized that’s how it works.

I was able to fix this by making sure to call await on refresh() before calling it a second time, but I think the default implementation should be to cancel the first promise when the data gets refreshed. There’s a TODO about this in the code for useAsyncData here. Given that useAsyncData is one of the core functions of the framework shouldn’t this get prioritized?

Here’s my (local) fix:

const { refresh, data } = useAsyncData(url, ...);
let pendingRefresh = null;
watch(url, async () => {
  if (pendingRefresh) {
    await pendingRefresh;
  }
  pendingRefresh = refresh();
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to refresh the data obtained by Async Data() in NuxtJs?
In pure Vue, I would write an ajax method to update the data from the server after removal. Usually this method is the...
Read more >
Understanding Difference Between Asyncdata Fetch Nuxt
Nuxt provides two useful hooks for fetching data: AsyncData and Fetch. They're available at different times in the Nuxt lifecycle, ...
Read more >
Nuxt 3 | Data fetching | useAsyncData | useFetch - YouTube
Hi all,Thanks a lot guys for voting in the poll that I ran last week. It was super helpful.As per the majority, here...
Read more >
Why Use Nuxt JS 3 Beta?! (Vue.js 3 With Nuxt Tutorial!!)
Nuxt JS 3 Beta has just been released? Should you use it in your next project? Does it hold up to the hype?...
Read more >
Async data made simple with React Query - Hey! I'm Tyler
A library of custom hooks that solves async data fetching and caching within ... key”, is to pass it an array of strings....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found