Skip to main content
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Pat Santora
Ben Nadel at cf.Objective() 2010 (Minneapolis, MN) with: Pat Santora ( @patweb99 )

Always Throw Errors In Order To Get A Stack Trace In Promise Chains

By on

The other day, I was developing a Promise-based workflow when I ran into a little dilemma. I had a situation in which I needed to raise an exception. But, the path forward, in the heat of the moment, was suddenly unclear; since I was already inside a Promise chain, should I throw the error or reject the error? Luckily, I didn't have to think about this too deeply because IE (Internet Explorer) forced me down the right path. In IE (both 10 and 11), the .stack property of the Error object isn't actually populated until the Error object is thrown. As such, you must throw the Error object in order get a proper stack trace in a Promise Chain (or anywhere else, for that matter).

To see this in action, I put together a tiny demo that rejects a Promise in two different ways: first, with the reject() function and second, with the throw() operation:

<!doctype html>
<html>
<head>
	<meta charset="utf-8" />

	<title>
		Always Throw Errors In Order To Get A Stack Trace In Promise Chains
	</title>
</head>
<body>

	<h1>
		Always Throw Errors In Order To Get A Stack Trace In Promise Chains
	</h1>

	<p>
		<em>Look at console &mdash; things being logged, yo!</em>
	</p>

	<script type="text/javascript" src="../../vendor/core-js/2.4.1/shim.min.js"></script>
	<script type="text/javascript">

		var promise = new Promise(
			function( resolve, reject ) {

				// If we REJECT instead of THROW ....
				reject( new Error( "Something went wrong!" ) );

			}
		);

		promise.catch(
			function handleReject( error ) {

				console.warn( "Error:" );
				console.log( error.message );

				// CAUTION: In IE 10 / 11, the stack property will be undefined because
				// the original Error() object was never thrown. IE only populates the
				// stack at the time the Error is thrown.
				console.log( error.stack );

			}
		);


		// --------------------------------------------------------------------------- //
		// --------------------------------------------------------------------------- //


		var promise = new Promise(
			function( resolve, reject ) {

				// If we THROW instead of REJECT ....
				throw( new Error( "Something went wrong (but better)!" ) );

			}
		);

		promise.catch(
			function handleReject( error ) {

				console.warn( "Error:" );
				console.log( error.message );

				// This time, since we threw the error, instead of simply rejecting it,
				// IE 10 and 11 will populate the stack trace.
				console.log( error.stack );

			}
		);

	</script>

</body>
</html>

As you can see, both approaches use the core Promise constructor to initiate the Promise chain. The first fulfills the Promise with the explicit rejection of the Error object. The second throws the Error which will implicitly fulfill the Promise with a rejection of the thrown Error object. In Microsoft Edge and all other modern browsers, the two approaches result in the same output; but, in IE 10 and 11, only the latter provides a stack trace:

IE 10 and 11 only populate the .stack property of an Error object when it's thrown.

As you can see, only a thrown Error provides a stack trace in IE 10 and 11.

In hindsight, my confusion seems silly. Of course you throw() Error objects - that's the whole point of creating an Error object. But, at the time, with the reject() function right there, I suddenly felt unsure of myself. Thankfully, IE was there to steer me in the right direction (and how many times do you get to say that in your life!?).

Want to use code from this post? Check out the license.

Reader Comments

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel