Jul 10, 2016

JavaScript Promises: Understanding Error Handling with Example

Promises are an alternative to callbacks for delivering the results of an asynchronous computation. All modern browsers have native support for Promises in JavaScript. In this post, we will see how error handler works with JavaScript chain promises. Before we get started, let's see how to create a promise:


var promise = new Promise(function(resolve, reject) {
  // do your async Job here
  if (/* all is well */) {
    resolve("Done!");
  }
  else {
    reject(Error("Failed!"));
  }
});

Here is how to use promise:


promise.then(function(result) {
  console.log(result); // "Done!"
}, function(err) {
  console.log(err); // Error: "Failed!"
});

The then method of the Promise object runs when the promise is completed or rejected, whichever occurs first. If the promise is completed successfully, the fulfillment handler function of the then method runs. If the promise is rejected, the error handler function of the then method (or the catch method) runs. You can also chain calls to the then method(i.e. promise.then(...).then(...).then(...)). Each completion handler must itself return a promise to support chaining.

then() takes two arguments, one for success, one for failure.

You can also use catch():


promise.then(function(result) {
  console.log(result); // "Done!"
}).catch(function(err) {
  console.log(err); // Error: "Failed!"
});

Notes:

1. .catch() = .then(undefined, func)

Syntactic sugar only

2. Promise rejection will go to NEXT rejection callback (either .then(resolveCallback, rejectionCallback) or in .catch(rejectionCallback) whichever is available first).

3. Both functions in .then never be called.

Let's understand the rules with an example.


var temp =5; 
function doJob(index) {   
	if (index % temp ==0){		
		throw new Error(index);
	}
	else{
		console.log('Success: ' + index);		
		return Promise.resolve();
	}
}

function errorHandler(err,index) {
   console.log('Error generated in '+ err + ', handled in ' + index);   
	if (index % temp ==0){		
		throw new Error(index);
	}
}

For better understanding, temp variable is used and if index%temp equals to 0 then the error will be thrown. We will change value of temp and see the results in following chain:


	doJob(1)

    .then(function(){ return doJob(2); })

	.then(function(){ return doJob(3); })  

    .then(function(){ return doJob(4); }) 

    .then(function(){ return doJob(5); }, function(err){ errorHandler(err,6); })
	
	.then(function(){ return doJob(7); }) 

	.catch(function(err){ errorHandler(err,8); })

	.then(function(){ return doJob(9); }) 

	.catch(function(err){ errorHandler(err,10); })

	.then(undefined, function(err){ errorHandler(err,11); })

Now Question for you, what would be output of the above chain for temp=5?

Okay... let's do analysis. The flow will be following:

1 > 2 > 3 > 4 > 5 (Error) > 8 > 9

As both methods of then can't be called at once so doJob(5) error will be handled in errorHandler(err,8).

Javascript Promise error handling

What would be output if temp=4?

The flow will be following:

1 > 2 > 3 > 4 (Error) > 6 > 7 > 9

The error generated in doJob(4) is handled by rejection callback errorHandler(err,6).

Javascript Promise error handling

What would be output if temp=3?

The flow will be following:

1 > 2 > 3 (Error) > 6 (Error) > 8 > 9 (Error) > 10

The different thing is errorHandler 6 is also throwing error in this case which is handled by errorHandler(err,8).

Javascript Promise error handling

Conclusion:

In this post, we saw how to create, use and chain native promise object in JavaScript and basic rules of Promise rejection flow with an example.

Hope, It helps. Feel free to ask query, suggestion in comment box.