Nickname0222022022
Nickname0222022022

Reputation: 616

Specific task for each async call and promise wait for all

Is it safe to use asyncs in javascript like this:

async coolFunction(users) {
  const firstPromise = findPrivilegesInOneDbAsync();
  const secondPromise = findPrivilegesInSecondDbAsync();
//LABEL_1
  firstPromise.then(privilege=> {
    users.forEach(user => {
      if(user.privCode === privilege.code) {
        user.privileges.push(privilege);
      }
    }
  }
//LABEL_2
  secondPromise.then(privilege=> {
    users.forEach(user => {
      if(user.altPrivCode === privilege.differentCode) {
        user.privileges.push(privilege);
        user.hasAlternativePrvis = true;
      }
    }
  }
//LABEL_3
  Promise.all([firstPromise, secondPromise]).then(() => {
    console.log("DONE!");
    //do something
  })
}

The question is, is it guaranteed that LABEL_3 - Promise.all callback gonna execute after first and second promise (order in those two of course does not matter) callbacks are done?

Upvotes: 2

Views: 36

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075039

...is it guaranteed that LABEL_3 - Promise.all callback gonna execute after first and second promise (order in those two of course does not matter) callbacks are done?

Yes, it is. The fulfillment handlers on a promise are called in order of registration. Since your earlier ones are registered before your Promise.all ones, they'll be run first.

Example:

function delay(ms, ...args) {
    return new Promise(resolve => {
        setTimeout(resolve, ms, ...args);
    });
}

const promise = delay(800);
promise.then(() => {
    console.log("first");
});

promise.then(() => {
    console.log("second");
});

But it would probably be more idiomatic to use the promises returned by then instead:

async coolFunction(users) {
  const firstPromise = findPrivilegesInOneDbAsync();
  const secondPromise = findPrivilegesInSecondDbAsync();
  Promise.all([
      firstPromise.then(privilege=> {
        users.forEach(user => {
          if(user.privCode === privilege.code) {
            user.privileges.push(privilege);
          }
        }
      },
      secondPromise.then(privilege=> {
        users.forEach(user => {
          if(user.altPrivCode === privilege.differentCode) {
            user.privileges.push(privilege);
            user.hasAlternativePrvis = true;
          }
        }
      }
  ])
  .then(() => {
    console.log("DONE!");
    //do something
  });
}

That would also have the advantage of waiting for any promises returned by those fulfillment handlers before executing the "done" logic.


It's probably worth noting that there's no reason for that method to be async if you're going to do things in parallel like that and use .then handlers rather than await. You could do this, though, to keep the processing of the first two things in parallel but wait for them both to finish:

async coolFunction(users) {
  const firstPromise = findPrivilegesInOneDbAsync();
  const secondPromise = findPrivilegesInSecondDbAsync();
  await Promise.all([
      firstPromise.then(privilege=> {
        users.forEach(user => {
          if(user.privCode === privilege.code) {
            user.privileges.push(privilege);
          }
        }
      },
      secondPromise.then(privilege=> {
        users.forEach(user => {
          if(user.altPrivCode === privilege.differentCode) {
            user.privileges.push(privilege);
            user.hasAlternativePrvis = true;
          }
        }
      }
  ])
  console.log("DONE!");
  //do something
}

That would also wait for any promises returned by those fulfillment handlers before executing the "done" logic.

Upvotes: 3

Related Questions