24

In my application I have a seller page which displays products listed by that seller. I am using asyncData to get all data required for the page (better for SEO)

asyncData ({params, app, error }) {

    return app.$axios.$get(`/seller/${params.username}`).then(async sellerRes => {

        let [categoriesRes, reviewsRes, productsRes] = await Promise.all([
            app.$axios.$get(`/categories`),
            app.$axios.$get(`/seller/${params.username}/reviews`),
            app.$axios.$get(`/seller/${params.username}/products`)
        ])

        return {
            seller: sellerRes.data,
            metaTitle: sellerRes.data.name,
            categories: categoriesRes.data,
            reviewsSummary: reviewsRes.summary,
            products: productsRes.data,
        }

    }).catch(e => {
        error({ statusCode: 404, message: 'Seller not found' })
    });
},

Although this method does the job intended, I can't help but think I am doing this wrong.

When navigating to the page the nuxt progress bar displays twice (which is odd).

I've been searching for a while now to try and find examples of multiple requests in asyncData but there's not much out there.

Maybe I'm not supposed to call multiple requests in asyncData?

1
  • Have you tried to await for the app.$axis.$get instead of returning it? Commented Jan 10, 2019 at 15:33

3 Answers 3

50

Try to use async await, this is how you can run both requests in parallel:

async asyncData ({ $axios }) {
  const [categoriesRes, articlesRes] = await Promise.all([ 
    $axios.get('/fetch/categories'),
    $axios.get('/fetch/articles'),
  ])

  return {
    categories: categoriesRes.data,
    articles: articlesRes.data,
  }
},
Sign up to request clarification or add additional context in comments.

4 Comments

I think this answer deserves to be adopted
That's a really cool example. I was thinking that I was executing requests in paralell but no...This is the way! Thank a lot!
How if one of the request is failing? How to catch it?
Actually Promise.all is not the best choice here. If one promise rejects, no other promise will be resolved ...
26
+25

Actually, you can, using the async await, which, looks a lot cleaner too.

<template>
  <div class="container">
    <h1>Request 1:</h1>
    <h1>{{ post.title }}</h1>
    <pre>{{ post.body }}</pre>
    <br />
    <h1>Request 2:</h1>
    <h1>{{ todos.title }}</h1>
    <pre>{{ todos.completed }}</pre>
  </div>
</template>

<script>
import axios from "axios";

export default {
  async asyncData({ params }) {
    // We can use async/await ES6 feature
    const posts = await axios.get(
      `https://jsonplaceholder.typicode.com/posts/${params.id}`
    );
    const todos = await axios.get(
      `https://jsonplaceholder.typicode.com/todos/${params.id}`
    );
    return { post: posts.data, todos: todos.data };
  },
  head() {
    return {
      title: this.post.title
    };
  }
};
</script>

here is a working sandbox of it. (don't forget to add a value for :id route param)

3 Comments

it works, but synchronously - check the answer of Andrew Savetchuk below if you want to run it in parallel
When one of those request is failed, then it throws 'data' is undefined
Also a issue to address here: Nuxt waits until a $axios promise resolves before loading the page. When your first call is fast and your second is slow, the page will already change state and the loading bar integrated in Nuxt will think that you are done and will disappear. Not really a neat feature if you have multiple calls waiting..
3

Maybe so?

asyncData ({params, app, error }) {

    return app.$axios.$get(`/seller/${params.username}`).then(sellerRes => {
        return Promise.all([
            app.$axios.$get(`/categories`),
            app.$axios.$get(`/seller/${params.username}/reviews`),
            app.$axios.$get(`/seller/${params.username}/products`)
        ]).then((categoriesRes, reviewsRes, productsRes) => {
            return {
                seller: sellerRes.data,
                metaTitle: sellerRes.data.name,
                categories: categoriesRes.data,
                reviewsSummary: reviewsRes.summary,
                products: productsRes.data,
            }
        })
    }).catch(e => {
        error({ statusCode: 404, message: 'Seller not found' })
    });

},

This is a chain of promises. The first promise tries to get information about the seller, if the request is successful, then a new request is created that will wait for the rest of the information.

Method asyncData will wait for all promises to complete and return the result of the call.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.