1

Im playing around with some async calls (AXIOS calls) involving promises. The problem with the code is the this.reloadData() gets called before this.updateUsers() and this.updateEmails() executed and finished. What is the right way to wait for the two functions finish, and then call this.reloadData() ?

rest.putEmail and rest.putUser are both axios REST API calls.

mainFunc() {
         Promise.all([this.updateUsers(), this.updateEmails()]).then(() => {
              this.reloadData();
         })

}

updateEmails() {
    const {emails} = this.state;
    if (emails.length > 0) {
         emails.map(user => {
               rest.putEmail(email.id, email.content)
                   .catch(err => {this.error(err)});
          });
    }
}

updateUsers() {
        const {users} = this.state;
        if (users.length > 0) {
             users.map(user => {
                   rest.putUser(user.id, user.name)
                       .catch(err => {this.error(err)});
              });
          }
    }
ssss
  • 21
  • 1
  • 7
  • 7
    In order for this to work, your functions need to return promises – Dave Jun 22 '18 at 19:24
  • @dave im calling rest calls for each item in a collection. How could i wrap all of this into a promise and then return it ? – ssss Jun 22 '18 at 19:26
  • 2
    Possible duplicate of [How to run after all javascript ES6 Promises are resolved](https://stackoverflow.com/questions/26634654/how-to-run-after-all-javascript-es6-promises-are-resolved) – Dave Jun 22 '18 at 19:26
  • @ssss You are already doing it in your first function: `Promise.all()` is the answer. – jelhan Jun 22 '18 at 20:11
  • Closely related: [Promise.all is returning an array of undefined and resolves before being done](/q/34813147/4642212), [How to use Promise.all() after Promises created in for loop](/q/42180299/4642212). – Sebastian Simon Jan 26 '23 at 15:29

1 Answers1

2

As stated in the comments, your updateEmails() and updateUsers() functions do not return promises and Promise.all accepts an array of promises as an argument. In this case, you're passing undefined as an argument to Promise.all so it doesn't wait for updateEmails() or updateUsers() to execute.

To solve this issue, you need to put all of your promise calls into an array, supply the array to Promise.all, and return that in both the updateEmails() and updateUsers() functions.

mainFunc() {
  Promise.all([this.updateUsers(), this.updateEmails()]).then(() => {
    this.reloadData();
  })
}

updateEmails() {
  const {emails} = this.state;
  if (emails.length > 0) {
    const promises = emails.map(user => {
        rest.putEmail(email.id, email.content)
            .catch(err => {this.error(err)});
    });
    return Promise.all(promises);
  }
}

updateUsers() {
  const {users} = this.state;
  const promises = [];
  if (users.length > 0) {
    const promises = users.map(user => {
      rest.putUser(user.id, user.name)
        .catch(err => {this.error(err)});
    });
    return Promise.all(promises);
  }
}

Whenever you call .map on both the emails and users arrays, an array of promises is returned which is stored in the const promises in both functions. Now you can simply pass these promises to Promise.all and return the promise returned from Promise.all. Now your Promise.all call inside of your mainFunc() is receiving promises it needs to wait for and won't call this.reloadData() until both functions have finished executing.

Jake Miller
  • 2,432
  • 2
  • 24
  • 39