The Right Way to Fetch Parallel Requests in Nuxt

When building a Nuxt application, you'll often need to fetch data from multiple APIs at the same time. A common approach is to use Promise.all() to run these requests in parallel, aiming for better performance.

However, doing it the wrong way will lead to some issues. Let's dive into the examples below to see what issues it might cause.

🚫 The Wrong Way: Raw Promise.all

const [latestAlbums, featuredAlbums, featuredArtists] = await Promise.all([
  $fetch("/api/albums/latest"),
  $fetch("/api/albums/featured"),
  $fetch("/api/artists/featured"),
]);

While this seems simple and efficient, it has a major issue in server-side rendering (SSR). Nuxt will first fetch the data on the server, and then again on the client after hydration—leading to unnecessary duplicate requests.

Using useFetch inside the Promise.all

You might want to say "We can just use useFetch then", but it's not a good solution either.

const [latestAlbums, featuredAlbums, featuredArtists] = await Promise.all([
  useFetch("/api/albums/latest"),
  useFetch("/api/albums/featured"),
  useFetch("/api/artists/featured"),
]);

At first glance, this looks better because useFetch should be only called on the server. However, if you try to do this, it will still result in duplicate requests in SSR.

✅ The Correct Way: useAsyncData with Promise.all

The solution is to wrap Promise.all inside useAsyncData and then create computed properties for each data we want to use.

const { data } = await useAsyncData(() =>
  Promise.all([
    $fetch("/api/albums/latest"),
    $fetch("/api/albums/featured"),
    $fetch("/api/artists/featured"),
  ]),
);

const latestAlbums = computed(() => data.value[0] ?? []);
const featuredAlbums = computed(() => data.value[1] ?? []);
const featuredArtists = computed(() => data.value[2] ?? []);

This is the best approach because we are using useAsyncData to fetch the data once on the server and then it will be present on the client side without any additional client-side requests.

🚀 Conclusion

If you're using Nuxt and need to fetch multiple APIs in parallel, avoid using raw Promise.all or useFetch directly. Instead, wrap Promise.all inside useAsyncData to get optimized, SSR-friendly, and efficient data fetching. This approach ensures your app runs smoothly while avoiding unnecessary network requests.