Promise errors in io.js

Datetime:2016-08-23 00:07:07          Topic: io.js           Share

See how to code native Promises and specific error detection in io.js. Recently the projects announced they are merging back together. While we wait for that merge to happen, there are still a few things you can do in io.js that are not yet available in node.js. One of those features is native Promises, part of ES6, along with some new io.js specific error detection.

Here’s the basic Promises feature:

var promise = new Promise(function(resolve, reject) {
  // do some async...
  if (true) {
	resolve("This works!")
  } else {
	reject(new Error("Broken."))
  }
})

promise.then(function(result) {
  console.log(result) // "This works!"
})

You'll notice that I don't have an error handler coded here for the rejections. It's best practice to do so, but there are still a lot of instances you can find where people have also forgotten them.

Let's see what happens when this code fails, instead of succeeds:

var promise = new Promise(function(resolve, reject) {
  // do some async...
  if (false) {
	resolve("This works!")
  } else {
	reject(new Error("Broken."))
  }
})

promise.then(function(result) {
  console.log(result) // "This works!"
})

That's right—nothing. It just silently fails. Luckily, io.js has a feature similar to process.on('uncaughtException') to trap any unhandled Promise rejections.

So let's just add that little snippet to the bottom of our last code sample:

process.on('unhandledRejection', function (err, p) {
  console.error(err.stack)
})

Now we should see:

Error: Broken.
	at /Users/mikeal/git/fun-with-promises/1.js:6:12
	at Object.<anonymous> (/Users/mikeal/git/fun-with-promises/1.js:1:77)
	at Module._compile (module.js:428:26)
	at Object.Module._extensions..js (module.js:446:10)
	at Module.load (module.js:353:32)
	at Function.Module._load (module.js:308:12)
	at Function.Module.runMain (module.js:469:10)
	at startup (node.js:124:18)
	at node.js:882:3

You'll notice that 'unhandledRejection' takes two arguments: the error instance as well as the promise that generated it. This is quite useful because you can add information to your Promises that might help you debug them later and even provide some context.

For instance, if you wanted some information about the HTTP request that generated an error:

var http = require('http')

http.createServer(function (req, res) {
  var promise = new Promise(function(resolve, reject) {
	// do some async...
	if (false) {
  	resolve("This works!")
	} else {
  	reject(new Error("Broken."))
	}
  })

  var p = promise.then(function(result) {
	console.log(result) // "This works!"
  })
  p.info = {url: req.url}
}).listen(8080)

process.on('unhandledRejection', function (err, p) {
  if (p.info && p.info.url) {
	console.log('Error in URL', p.info.url)
  }
  console.error(err.stack)
})

Now let's use curl to test.

> curl http://localhost:8080/mytest

Error in URL /testurl
Error: Broken.
	at /Users/mikeal/tmp/test.js:9:14
	at Server.<anonymous> (/Users/mikeal/tmp/test.js:4:17)
	at emitTwo (events.js:87:13)
	at Server.emit (events.js:169:7)
	at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:471:12)
	at HTTPParser.parserOnHeadersComplete (_http_common.js:88:23)
	at Socket.socketOnData (_http_server.js:322:22)
	at emitOne (events.js:77:13)
	at Socket.emit (events.js:166:7)
	at readableAddChunk (_stream_readable.js:145:16)

Isn’t that nice :)





About List