12

I have recently been reading about async/await and using try and catch to handle promise rejections, and have been applying it to some of my old code.

I have the following:

async function() {
    try {
        await Promise.all([some functions]);
        doIfNoError();
    } catch (error) {
        console.log(error);
    }

The functions I am passing to Promise.all follow the form:

async function() {
    some code
    if (some condition) {
        return true
    } else {
        throw false
    }
 }

I intend that if any of the functions passed into Promise.all reject, the rejection is displayed. If none of the functions reject, then doIfNoError should fire. However, doIfNoError sometimes fires when it shouldn't, and I am given the error "Unhandled Promise Rejection".

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
tom894
  • 459
  • 1
  • 3
  • 14
  • maybe your `doIfNoError` function is doing some job that throws an error. Could you please add a real example here ? – Raj Kumar Dec 30 '18 at 20:42
  • https://stackoverflow.com/questions/40500490/what-is-an-unhandled-promise-rejection – Gabriel Dec 30 '18 at 20:43
  • 1
    Also the function you are passing in Promise.all, try to pass a promise. It will either reject or resolve the promise and not just return or throw some value. eg: Promise.resolve(true) or Promise.reject(false) – Raj Kumar Dec 30 '18 at 20:44
  • 1
    You must *call* your function and pass the resulting promises in the array to `Promise.all`, not the functions themselves. – Bergi Dec 30 '18 at 20:47
  • 1
    Please post the actual code. Your `try`/`catch` code is fine, it must be either the calls or the contents of the `async function`s. – Bergi Dec 30 '18 at 20:49
  • 3
    `await Promise.all([some functions])` should be `await Promise.all([some promises]);` – Mulan Dec 30 '18 at 20:57
  • @user633183 `Promise.all` can take an array of functions (or even constants), so long as they return "resolved" values, i.e. `Promise.all([Promise.resolve(), 1, true, () => (3)]);` will work just fine. – Drew Reese Dec 31 '18 at 00:12

3 Answers3

14

Actually, try/catch does work well with Promise.all().

Here is a snippet to prove it:

async function p1() {
  return 1;
}

async function boom() {
  return new Promise((resolve, reject) => {
    setTimeout(() => reject('boom'), 100)
  })
}

// expected output: 'boom', ["value before Promise.all"]
async function asyncCall() {
  let all = ['value before Promise.all'];

  try {
    all = await Promise.all([p1(), boom()]);
  } catch (e) {
    console.log("caught error:", e);
  }

  console.log(all);
}

asyncCall();
Community
  • 1
  • 1
Pleymor
  • 2,611
  • 1
  • 32
  • 44
4

Try using promises to their full potential, which includes a catch block for rejected promises. Note that if doIfNoError also throws an error, it will be caught with catch.

async function() {
    await Promise.all([some promises])
    .then(doIfNoError) // Promise.all resolved
    .catch(console.log) // Promise.all has at least one rejection
}

promiseAll = async (promises) => {
  await Promise.all(promises)
  .then(doIfNoError) // Promise.all resolved
  .catch(console.log) // Promise.all has at least one rejection
}
    
doIfNoError = () => console.log('No errors');

promiseAll([Promise.resolve(), 1, true, () => (false)]);
promiseAll([Promise.resolve(), 1, true, Promise.reject('rejected: because reasons'), Promise.resolve()]);

It's often considered bad practice to mix async/await with Promise chains. Using a try/catch should work just fine.

promiseAll = async (promises) => {
  try {
    await Promise.all(promises);
    doIfNoError(); // Promise.all resolved
  } catch(error) {
    console.log(error); // Promise.all has at least one rejection
  }
}
    
doIfNoError = () => console.log('No errors');

promiseAll([Promise.resolve(), 1, true, () => (false)]);
promiseAll([Promise.resolve(), 1, true, Promise.reject('rejected: because reasons'), Promise.resolve()]);
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
2

1) throw false – this does not make sense, you should not throw a boolean but an instance of Error instead.

2) catch is only triggered when an error is thrown or the promise is "rejected" (note: reject and throw have the same effect with async-await). In contrast: "Resolving" a promise with a boolean value of false is not interpreted by async-await as an exception. So make sure you throw an error or reject the promise if you want the catch-block to kick in. if you reject, pass the exception as argument to reject, e.g. (Promise.reject(new Error("Something went wrong")).

Apart from what I mentioned above, your code looks fine.

StudioTime
  • 22,603
  • 38
  • 120
  • 207
Felix K.
  • 14,171
  • 9
  • 58
  • 72