Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle catch blocks and then of Promise [duplicate]

I have following code

function request(status){
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(status){
        resolve('Success');
      } else {
        reject('error');
      }
    }, 1000);
  }); 
}


let promise = request(false);

promise.then( response => {
  console.log('response' , response);
});

promise.catch( (err) => {
  console.log('got Error', err);
});

throws following error even I caught the reject response

got Error error (node:11252) UnhandledPromiseRejectionWarning: error (node:11252) 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:11252) [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.

but if I remove the then block then it works fine, NO STACK TRACE ERROR ON THE CONSOLE

function request(status){
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(status){
        resolve('Success');
      } else {
        reject('error');
      }
    }, 1000);
  }); 
}


let promise = request(false);

promise.catch( (err) => {
  console.log('got Error', err);
});

Output:

got Error error

I do not understand why it works in such a way?

like image 735
Thamaraiselvam Avatar asked Dec 23 '22 04:12

Thamaraiselvam


2 Answers

The key thing here — and one of the key things about using promises — is that then and catch create new promises. So the promise that was rejected that wasn't handled was the one created by then:

let promise = request(false);

promise.then( response => {          // Creates new promise, rejection isn't handled
  console.log('response' , response);
});

promise.catch( (err) => {            // Creates new promise
  console.log('got Error', err);
});

This is one of the reasons you see promise chains:

request(false)
.then( response => {
  console.log('response' , response);
})
.catch( (err) => {
  console.log('got Error', err);
});

There, three promises are still created (the original from request, the one from then, and the one from catch), but rejection is handled for all three of them by the final catch handler.

The promise created by then and catch work like this:

  • If the underlying promise resolves:
    • If there's no then handler, resolve with the resolution from the original promise
    • If there's a then handler, call it:
      • If the handler returns a thenable (a promise-like object), hook up to it and resolve or reject based on whether that thenable resolves or rejects
      • If the handler returns a non-thenable value, resolve with that value
      • If the handler throws an error, reject with that error
  • If the underlying promise rejects:
    • If there's no catch handler, reject with the rejection from the original promise
    • If there's a catch handler, call it and do exactly what's done with the then handler above (resolve or reject based on what it returns or throws)
like image 171
T.J. Crowder Avatar answered Jan 06 '23 05:01

T.J. Crowder


promise.then() creates a new promise whose settlement depends on promise. When promise is rejected, the implicit promise created by promise.then() is also rejected and has no catch() clause to handle the error.

What you need to do is chain the .catch() to the promise returned by promise.then():

function request(status){
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(status){
        resolve('Success');
      } else {
        reject('error');
      }
    }, 1000);
  }); 
}


let promise = request(false);

promise.then( response => {
  console.log('response' , response);
}).catch( (err) => {
  console.log('got Error', err);
});
like image 29
Patrick Roberts Avatar answered Jan 06 '23 05:01

Patrick Roberts