3
votes

I am having an error: (node:6186) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): threep (node:6186) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. -------- ones ========= two CaughtCathchError threep (node:6186) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1) I am consuming my 3 promise functions in nested order. p1,p2,p3- are my promise functions as shown below. i tried adding promise reject in all p1,p2,p3 functions as well but its still the same

enter code here
var p1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
       // resolve('ones')
                resolve('ones')
    }, 9000)
})
var p2 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        // throw new Error('eeeee');
        //reject('two')
    resolve('two')
    }, 1000)
})
var p3 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        reject('three')
    }, 4000)
})

p1.then(function(result){
    console.log("--------", result)
        // return p2.then(function(res){console.log(res)}).catch(function(err){console.log(err)})
        return p2
}).then(function(p2result){
    console.log("=========", p2result)
    return p3;
}).then(function(p3result){
    console.log('*********', p3result)
}).catch(function(err){
    console.log("CaughtCathchError", err)
})
3
see that line p3 = new Promise etc ? you're not handling that rejection - Jaromanda X
This is basically a limitation in the unhandled rejection detection logic where it reports the unhandled rejection even though the rejection does end up in a .catch(). - jfriend00

3 Answers

3
votes

p3 is a standalone Promise with no .catch. So, when p3 gets rejected, you get a UnhandledPromiseRejectionWarning. Even if p3 is consumed later in a Promise chain that has a proper catch, p3 itself does not have a catch.

Instead of p3, you might use a function that returns a Promise, and ensure that all calls to that function are caught:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
       // resolve('ones')
                resolve('ones')
    }, 1000)
})
var p2 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        // throw new Error('eeeee');
        //reject('two')
    resolve('two')
    }, 1000)
})
var getp3 = () => new Promise(function (resolve, reject) {
    setTimeout(function () {
        reject('three')
    }, 1000)
})

p1.then(function(result){
    console.log("--------", result)
        // return p2.then(function(res){console.log(res)}).catch(function(err){console.log(err)})
        return p2
}).then(function(p2result){
    console.log("=========", p2result)
    return getp3();
}).then(function(p3result){
    console.log('*********', p3result)
}).catch(function(err){
    console.log("CaughtCathchError", err)
})

If you need to initialize p3 immediately, then put a catch after the p3 itself.

2
votes

Node.js promise implementation expects rejected promise to be chained with catch(...) or then(..., ...) synchronously, otherwise PromiseRejectionHandledWarning appears. Unhandled promise rejections may result in exception in future.

Usually a rejection should be treated as any other error, so it's preferable for it to be an instance of Error and not plain string. Then it could be treated as such:

class ExpectedRejection extends Error {}

var p3 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve(new ExpectedRejection('three'))
    }, 4000)
})

...
.then(function(p3result){
  if (p3result instanceof ExpectedRejection)
    throw p3result;

  console.log('*********', p3result)
}).catch(function(err){
    console.log("CaughtCathchError", err)
})

ExpectedRejection class is specific and possibly not needed; could be replaced with Error everywhere because Error resolutions are uncommon.

This solution is not very common because if promises are created at the same time, they don't depend on each other and usually can be handled with Promise.all:

Promise.all([p1, p2, p3])
.then(function(p1result, p2result, p3result){
    console.log('*********', p3result)
}).catch(function(err){
    console.log("CaughtCathchError", err)
});

Notice that since p1, p2 and p3 are delays that are created at the same time, resulting catch will be triggered after 9 seconds (maximum duration of a delay) in both cases.

0
votes

If you want to create a rejecting/rejected promise that will be caught on the queue and not on the stack then you could do the following:

var p3 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        reject('three')
    }, 400)
});
//do not warn for p3 rejection but if you use it later (p3.then) or
//  return it in a promise chain you will have to catch it again
p3.catch(ignore=>ignore);