then function getting executed before all the asyn

2019-06-14 13:14发布

问题:

I am calling a backend service to fetch all the IDS available in the first fetch from the loadContent method and I am getting all the IDS from backend.

With the randomly picked 10 IDS from the initial service, I am calling another service individualy to fetch the complete data of the ID. I am also able to get all the data, but before getting all the data the function with dispatch is getting called due to which the data is not getting set in the store.

export function loadContent(requestUrl) {
  return dispatch => {

   return fetch( /* initial calls to get all the ids */ ).then((response) => {
      return response.json();
    }).then((data) => {
      console.log(data);
      var stories = [];


      var x = 0;
      var loopArray = function(data) {
      return customAlert(data, function() {


        });
      }

      function customAlert(topStories, callback) {
        var randomNumber = topStories[Math.floor(Math.random() * topStories.length)];
        fetch( /* call service with individual id */ ).then((response) => {
          return response.json();
        }).then((output) => {
          console.log(output);
          stories[x] = output;
          x++;

          // any more items in array? continue loop
          if (x <= 10) {
            loopArray(data);
          } else {
            return stories;
          }
        })
      }
     return loopArray(data);
    }).then((stories) => {
      dispatch({
        type: "LOAD",
        payload: stories
      });
    }).catch((err) => {
      console.log("There has been error");
    })


  };
}

export function load(news) {
  return {
    type: 'LOAD',
    news: news
  }
}

回答1:

You need to return each Promise from its inner block so that you can chain them all together and have the .then((stories) execute only once they're all complete. Namely, change to:

return fetch( /* initial calls to

// ...

return customAlert(data, function() {

// ...

return fetch('to get the...

// ...

if (x <= 10) {
  return loopArray(data);
}

so that the initial call of

return loopArray(data);

will only finally resolve once every other Promise (now properly chained with the initial call) has resolved.

You also might simplify your code by using push, for example:

stories.push(output);

rather than keep an x variable of the current length of the stories array so you can assign to stories[x].

Also, you may consider using Promise.all if you're able to make promises in parallel, so as to reduce the time necessary for the whole function to complete.