Dev
Dev

Reputation: 423

Promise.all getting Unhandled rejection

I'm using Promise.all and catch error but still getting Unhandled rejection

const Promise = require('bluebird');

function sleep(milis) {
return new Promise(function(resolve, reject) {
    if (milis == 1000) {
        console.log('Rejecting millis', milis)
        setTimeout(() => {
            reject('Got error')
        }, milis);

    } else {
        console.log('Processing millis', milis)
        setTimeout(() => {
            resolve(milis);
        }, milis);

    }
});
}

function test() {

try {
    let lists = [2000, 1000, 3000]
    Promise.all(
            lists.map(record => {
                try {
                    sleep(record)
                } catch (err) {
                    console.log('Error inside catch block1', err)
                    throw err
                }
            })
        ).then(data => {
            console.log('Resolved', data)
        })
        .catch(err => {
            console.log('Error inside catch block2', err)
            throw err

        });

} catch (err) {
    console.log('Error inside catch block3', err)
}
}


test();

After using catch block why still getting Unhandled rejection. Any help appreciated. But if I use async await not getting Unhandled rejection.

Upvotes: 0

Views: 4917

Answers (3)

Lennholm
Lennholm

Reputation: 7470

There are multiple issues with your code, let's step through them one by one:

Firstly

When you're mapping your lists array you never return the promise you get from your sleep() function. This means that what you provide to Promise.all() is an array filled with undefined. Promise.all() treats values that are not promises as a resolved promise, so your Promise.all() will always resolve regardless of whether the promises created by sleep() resolve or reject. This also means that nothing catches a rejected promise from sleep() and this is why your script is currently getting unhandled promise rejections.
You fix this by returning the promise properly with return sleep(record). But this won't be enough to get rid of all unhandled promise rejections so let's move on...

Secondly

You have wrapped your calls to sleep() in a try-catch block. Unless you're using async-await, a try-catch block will not catch rejected promises. In this case it will only catch errors thrown when the promise is created. That's all fine if that was your intent but if your intent was to catch the rejected promises it's not going to work.

Thirdly

You have attached a catch() handler to your Promise.all(). Unlike the aforementioned try-catch, that actually takes care of any rejected promises. However, you re-throw the error in this handler which means the promise chain will still be rejected. You have wrapped your Promise.all() in another try-catch block but as mentioned, this doesn't catch rejected promises so the still rejected promise will end up being unhandled.
In this case, you should simply not re-throw the error in your last catch() handler as I can't see any point in doing so here. If you for whatever reason need to re-throw it you need to add another catch() handler later in the chain.

Upvotes: 4

narayansharma91
narayansharma91

Reputation: 2353

The reason is you are not handling error on this sleep method. It should look like this.

function sleep(milis) {
return new Promise(function (resolve, reject) {
    if (milis == 1000) {
        console.log('Rejecting millis', milis)
        setTimeout(() => {
            reject('Got error')
        }, milis);

    } else {
        console.log('Processing millis', milis)
        setTimeout(() => {
            resolve(milis);
        }, milis);

    }
 }).catch(error => {
    console.log(error);
 })
}

Upvotes: 1

afenster
afenster

Reputation: 3608

TL;DR: throw err inside .catch handlers are not caught by any other catch in your code, so you get unhandled promise rejections.

First of all, in this code snippet

lists.map(record => {
  try {
    sleep(record)
  } catch (err) {
    console.log('Error inside catch block1', err)
    throw err
  }
})

the result of the .map will be [undefined, undefined, undefined], since the function does not return any value. You need to write return sleep(record) if you want it to return a promise for each list element.

Then, please note that the main catch block is executed before .then/.catch handlers of Promise.all. If you add console.log after your main catch block, you'll see it. That means that the exceptions you are re-throwing in your .catch handlers are not caught by anything, and are shown as unhandled.

Upvotes: 1

Related Questions