If you haven't read part I, I would recommend that you take a look at it here.
If you've read part I, you may have wondered when will the reject function be called and how to specify a real reject function to the Promise.
Actually, in the previous part, to make life simple, we've ignored the reject function. The full version of .then() should come with 2 parameter: resolve and reject function.
Reject function
To be clearer on this, let's open our cool console tab in chrome and type the following codevar p1 = new Promise(function(resolve, reject) { console.log('1'); throw 'Uh-oh!'; }); p1;The console outputs would be like below:
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "Uh-oh!"}Ok, something have changed. p1's status is now rejected and its PromiseValue is now "Uh-oh!".
What happened was that during its execution, p1 met an error (exception) and it cannot be resolved, but was rejected. Thus its status is rejected and the exception is saved in the PromiseValue, so that it can be passed to the reject function if specified.
Now let's try to specify the resolve function as we did in the previous part:
var p2 = p1.then(function(val) { console.log('2: ' + val); return val; }); p2;The console outputs would be:
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "Uh-oh!"}p2 status is also rejected and the PromiseValue is forwarded to p2. More over, the resolve function was not called because there was no console log output.
Let's change p2 a little bit by adding a reject function to .then()
var p2 = p1.then( function(val) { console.log('resolve 1: ' + val); return val; }, function(err) { console.log('reject 1: ' + err); return err; } ); p2;The console outputs would now be:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "Uh-oh!"}p2 is now resolved, the console logs "reject 1: Uh-oh!" and the PromiseValue is "Uh-oh!", which is because we called return err; in the reject function.
In the code above, we pass to .then() 2 params, the first one is the resolve function to call when p1 succeeds, the second one is the reject function to call when p1 fails. Since p1 is rejected, the reject function is called. There's no error during execution of p2 so p2 status is resolved.
Now if we run the following code:
var p3 = p2.then( function(val) { console.log('resolve 2: ' + val); return val; }, function(err) { console.log('reject 2: ' + err); return err; } ); p3;The console outputs would be as below:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "Uh-oh!"}We can see that the resolve function was called and p3 is resolved .
then() and catch()
To make life even simpler and code even clearer, Promise provides us with another helpful function: catch()Instead of writing this:
var p2 = p1.then( function(val) { console.log('resolve 1: ' + val); return val; }, function(err) { console.log('reject 1: ' + err); return err; } ); p2;We can now write this:
var p2 = p1 .then(function(val) { console.log('resolve 1: ' + val); return val; }) .catch(function(err) { console.log('reject 1: ' + err); return err; }) p2;Which will basically execute and output the same thing:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "Uh-oh!"}Technically, the call to .catch(rejectFunction) is equal to calling .then(undefined, rejectFunction) and in the the above code, there was actually another promise in between, right after the first .then(). So the above code is actually:
var p1_1 = p1 .then(function(val) { console.log('resolve 1: ' + val); return val; }); p1_1; var p2 = p1_1.catch(function(err) { console.log('reject 1: ' + err); return err; }) p2;One good thing about Promise is that if an error is not handled by a promise, it make the promise rejected and keep forwarding the error to the next promise. Therefore in the above code, p1 does not have a reject function so p1_1's status is rejected and the error get passed to the next promise. Since p1_1 has a reject function (specified by .catch()), p2 is resolved.
If we don't use .catch(), and specified the reject function inside of a .then(), then we must specified the next layer of resolve and reject function inside of the first reject function, and if this keeps going on, we would end up in the same callback hell as when we don't use Promise at all.
By using .catch(), the error handling would also be much simpler when we chain promise after promise like this:
var p2 = p1 .then(resolveFunc1) .then(resolveFunc2) .then(resolveFunc3) .then(resolveFunc4) .catch(rejectFunc);When we write like this, if error happens during any node of the promise chain, the rejectFunc will be called.
We can also catch the error for a particular promise separately like this:
var p2 = p1 .then(resolveFunc1) .then(resolveFunc2) .catch(rejectFunc2) .then(resolveFunc3) .then(resolveFunc4) .catch(rejectFunc);In this part, you've learned how to handle errors using reject function and .catch(). We will discuss more on Promise chain in the next part of this blog series. That's it for part II.
No comments:
Post a Comment