Search code examples
promisefetchnuxt.js

How to use a few dispatch in nuxt fetch?


I create a site in nuxt and got data from worpdress api. I have a few store: home.js, solutions.js, tipo.js, portfolio.js and options.js.

In fetch i check, if the store array is empty, than call dispatch and fill arrays.

export default {
  async fetch({ store }) {
    try {
      if (store.getters['home/home'].length === 0) {
        await store.dispatch('home/fetchHome');
      }
      if (store.getters["solutions/getSolutions"].length === 0) {
        await store.dispatch('solutions/fetchSolutions');
      }
      if (store.getters["tipo/getTipo"].length === 0) {
        await store.dispatch('tipo/fetchTipo');
      }
      if (store.getters["portfolio/getPortfolio"].length === 0) {
        await store.dispatch('portfolio/fetchPortfolio');
      }
      if(store.getters["options/getOptions"].length === 0){
        await store.dispatch('options/fetchOptions');
      }
    } catch (e) {
      console.log(e, 'e no data')
    }
  },
  components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
}

But the problem is, that the page is loading to long time. Because i call dispatches throw await, and i think, this is the problem.

How can i call all dispatches in fethc, without async, but parallel?

I see the advantage of working with fetch over asyncData in that only the first time when I load the page, I need to wait a little, the arrays will fill up and when I get to the current page from another page, there will be no requests through the api, and the data will be output from the store.

It's just that there is very little information on nuxt in terms of ideology, how to work and what is better to use and when. In next, this is better.

This method doesn't work.

fetch({ store }) {
  const promise1 = new Promise((resolve, reject) => {
    if (store.getters['home/home'].length === 0) {
      resolve(store.dispatch('home/fetchHome'));
    }
  });
  const promise2 = new Promise((resolve, reject) => {
    if (store.getters["solutions/getSolutions"].length === 0) {
      resolve(store.dispatch('solutions/fetchSolutions'));
    }
  });
  const promise3 = new Promise((resolve, reject) => {
    if (store.getters["tipo/getTipo"].length === 0) {
      resolve(store.dispatch('tipo/fetchTipo'));
    }
  });
  const promise4 = new Promise((resolve, reject) => {
    if (store.getters["portfolio/getPortfolio"].length === 0) {
      resolve(store.dispatch('portfolio/fetchPortfolio'));
    }
  });
  const promise5 = new Promise((resolve, reject) => {
    if (store.getters["options/getOptions"].length === 0) {
      resolve(store.dispatch('options/fetchOptions'));
    }
  });
  Promise.all([promise1, promise2, promise3, promise4, promise5])
    .then((data) => console.log(data))
    .catch((error) => console.log(error));


Solution

  • Assuming that:

    • store.dispatch() returns Promise,
    • the first attempt in the question is generally correct,
    • the objective is to perform relevant dispatches in parallel,

    then:

    • elimitate await from the store.dispatch() sequence,

    • accumulate the promises returned by store.dispatch() in an array,

    • don't use a new Promise() wrapper,

    • await the Promise returned by Promise.all(promises).

      export default {
          async fetch({ store }) {
              try {
                  let promises = [];
                  if (store.getters['home/home'].length === 0) {
                      promises.push(store.dispatch('home/fetchHome'));
                  }
                  if (store.getters['solutions/getSolutions'].length === 0) {
                      promises.push(store.dispatch('solutions/fetchSolutions'));
                  }
                  if (store.getters['tipo/getTipo'].length === 0) {
                      promises.push(store.dispatch('tipo/fetchTipo'));
                  }
                  if (store.getters['portfolio/getPortfolio'].length === 0) {
                      promises.push(store.dispatch('portfolio/fetchPortfolio'));
                  }
                  if(store.getters['options/getOptions'].length === 0) {
                      promises.push(store.dispatch('options/fetchOptions'));
                  }
                  let data = await Promise.all(promises);
                  console.log(data);
              } catch (e) {
                  console.log(e);
              }
          },
          components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
      }
      

    For convenience, this can be proceduralised as follows:

    export default {
        async fetch({ store }) {
            try {
                let paths = [
                    { get: 'home/home',              fetch: 'home/fetchHome' },
                    { get: 'solutions/getSolutions', fetch: 'solutions/fetchSolutions' },
                    { get: 'tipo/getTipo',           fetch: 'tipo/fetchTipo' },
                    { get: 'portfolio/getPortfolio', fetch: 'portfolio/fetchPortfolio' },
                    { get: 'options/getOptions',     fetch: 'options/fetchOptions' }
                ];
                let promises = paths.filter(p => store.getters[p.get].length === 0).map(p => store.dispatch(p.fetch));
                let data = await Promise.all(promises);
                console.log(data);
            } catch (e) {
                console.log(e);
            }
        },
        components: { HomeContacts, PortofolioSlider, Clients, ChiSiamo, Solutions, HomeIntro }
    }
    

    It may make more sense to define the paths array elsewhere in the code and pass it to a simplified fetch(), giving it the profile :

        fetch({ store, paths })
    

    If it still doesn't work, then there's something your're not telling us.