Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decide which promise does a then/catch according to

All:

I am pretty new to Promise, here is an example:

var someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // this will throw, x does not exist
    resolve(x + 2);
  });
};

var someOtherAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    reject('something went wrong');
  });
};

someAsyncThing().then(function() {
  return someOtherAsyncThing();
}).catch(function(error) {
  console.log('oh no', error);
});

I do not quite get how .then() works with Promise, right now I can understand the someAsyncThing() return a Promise, which will generate an exception and thus go to .catch() part. And if we change resolve(x+2) to resolve(4), then it will go to run someOtherAsyncThing(); and return another promise,

the first question is if the return of .then() is the that Promise?

And second question, if in someOtherAsyncThing()'s Promise, I use resolve(x+2) to cause an exception, then it will also go to same .catch() part, then how can I make that .catch() only catch exception caused by someAsyncThing()'s promise(and same question for chained .then() if there is any)?

Thanks

like image 970
Kuan Avatar asked Dec 12 '15 00:12

Kuan


Video Answer


3 Answers

the first question is if the return of .then() is the that Promise?

p.then() returns a promise - always. If the callback passed to the .then() handler returns a value, then the newly returned promise will be resolved at the same time as the parent promise, but will be resolved with the returned value from the handler.

If the .then() handler returns a promise, then the promise returned by .then() is not fulfilled/rejected until the promise returns by the handler is fullfilled/rejected. They are chained together.

If the .then() handler throws, then the promise returned by .then() is rejected with the exception as the value. Throwing is the same as returning a rejected promise.

if in someOtherAsyncThing()'s Promise, I use resolve(x+2) to cause an exception, then it will also go to same .catch() part, then how can I make that .catch() only catch exception caused by someAsyncThing()'s promise(and same question for chained .then() if there is any)?

The beauty of promises is that errors propagate up the chain until handled. The way you stop err propagation at any level is to handle the error there.

If you want to separate the .catch() opportunities, then you have to just catch at a lower level. For example:

someAsyncThing().then(function() {
  return someOtherAsyncThing().catch(function(err) {
      // someOtherAsyncThing rejected here
      // you can handle that rejection here and decide how you want to proceed

      // for example, suppose you just want to handle the rejection, log it
      // and then continue on as if there was no problem, you can just return
      // a value here
      return 0;
  });
}).catch(function(error) {
  console.log('oh no', error);
});
like image 196
jfriend00 Avatar answered Nov 12 '22 09:11

jfriend00


Errors bubble up in promises until they're caught.

If you have the following (<= indicates contains):

Promise1 <= Promise2.catch(e) <= Promise3 <= throw

Then Promise3 throws and rejects. Promise2 rejects and then is caught. Promise1 resolves successfully because it receives no rejection.

Promise1 <= Promise2.catch(e) <= Promise3 <= throw
^ resolves  ^ rejects            ^ rejects

Think of it as an async try/catch.

Promise1 = Promise.reject(err); // or throw

Promise2 = Promise1.catch(err => {
  // error caught
});

Promise3 = Promise1.catch(err => {
  throw err;
  // error not caught but thrown back
});

// Now Promise1 is rejected. Promise2 is resolved. Promise3 is rejected.

You also need to know that each then/catch call creates a new Promise. I suggest you read the Promises/A+ spec and keep it as a reference.

like image 29
Louay Alakkad Avatar answered Nov 12 '22 09:11

Louay Alakkad


You can catch() on the inner Promise:

a().then(function() {
  return b().catch(function() {
    console.log('boo');
  });
}).catch(function(error) {
  console.log('oh no', error);
});

If a() rejects, "oh no" will be logged. If b() rejects, "boo" will be logged, but not "oh no".

like image 26
Félix Saparelli Avatar answered Nov 12 '22 09:11

Félix Saparelli