DJL
DJL

Reputation: 2200

UnhandledPromiseRejectionWarning followed by PromiseRejectionHandledWarning

The following code gives an UnhandledPromiseRejectionWarning for p2, despite errors on p2 being explicitly handled.

function syncFunctionReturnsPromise(val)
{
  return new Promise((r,x)=> {
    setTimeout(()=> {
      if (val) { 
        r('ok');
      } else {
        x('not ok');
      }
    }, val?1000:500);
  });
}

async function test(){
  let p1 = syncFunctionReturnsPromise(true);
  let p2 = syncFunctionReturnsPromise(false); 
  await p1.catch(ex => console.warn('warning:', ex));  //errors in these 2 promises
  await p2.catch(ex => console.warn('warning:', ex));  //are not the end of the world
  console.log('doOtherStuff');
}
test();

The output looks like this:

(node:9056) UnhandledPromiseRejectionWarning: not ok
(node:9056) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9056) [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.
warning: not ok
doOtherStuff
(node:9056) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)

It is not immediately obvious to me why this should be

Upvotes: 3

Views: 697

Answers (2)

sreepurna
sreepurna

Reputation: 1666

Here is the other way:

async function test(){
  let p1 =  await syncFunctionReturnsPromise(true)
                .catch(ex => console.warn('warning:', ex));
  let p2 =  await syncFunctionReturnsPromise(false)
                .catch(ex => console.warn('warning:', ex)); 
  console.log('doOtherStuff');
}

Upvotes: 0

DJL
DJL

Reputation: 2200

So this is because the first await waits synchronously before the handler is attached to p2. But p2 fails before p1 completes.

So node detects that p2 failed without any error handling.

N.B. In later versions of node this may cause the program to terminate, rather than just a warning.

The fix is to attach the handlers before awaiting

async function test(){
  let p1 = syncFunctionReturnsPromise(true);
  let p2 = syncFunctionReturnsPromise(false); 
  p1 = p1.catch(ex => console.warn('warning:', ex));  //errors in these 2 promises
  p2 = p2.catch(ex => console.warn('warning:', ex));  //are not the end of the world

  await p1;
  await p2;
  console.log('doOtherStuff');
}

Obviously you could inline that on the declaration although in my realworld code its neater as separate lines.

Upvotes: 5

Related Questions