Skip to content

Commit

Permalink
Catches errors from Promises / Async functions
Browse files Browse the repository at this point in the history
When returning Promises from a route handler either explicitly or implicitly by using Async Functions,default error handling is lost.

```
// Error caught and forwarded as expected
app.get('/', (req, res) => {
  throw new Error('Oh crap!')
})

// Error swallowed and lost
app.get('/', async (req, res) => {
  throw new Error('Oh crap!')
})
```
  • Loading branch information
leebyron committed Aug 14, 2016
1 parent 0ff58c6 commit 05eae10
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
24 changes: 22 additions & 2 deletions lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ Layer.prototype.handle_error = function handle_error(error, req, res, next) {
}

try {
fn(error, req, res, next)
var result = fn(error, req, res, next)
if (isPromise(result)) {
result.then(null, next)
}
} catch (err) {
next(err)
}
Expand All @@ -90,7 +93,10 @@ Layer.prototype.handle_request = function handle(req, res, next) {
}

try {
fn(req, res, next)
var result = fn(req, res, next)
if (isPromise(result)) {
result.then(null, next)
}
} catch (err) {
next(err)
}
Expand Down Expand Up @@ -173,3 +179,17 @@ function decode_param(val){
throw err
}
}

/**
* Returns true if the val is a Promise.
*
* @param {any} val
* @return {boolean}
* @private
*/

function isPromise(val) {
return val !== null &&
typeof val === 'object' &&
typeof val.then === 'function'
}
34 changes: 34 additions & 0 deletions test/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,40 @@ describe('Router', function () {
.get('/foo')
.expect(500, 'caught: oh, no!', done)
})

it('should handle a returned rejected promise', function(done) {
// Only run this test in environments where Promise is defined.
if (!global.Promise) {
return done();
}

var router = new Router()
var route = router.route('/foo')
var server = createServer(router)

route.all(function createError(req, res, next) {
return new Promise(function () {
throw new Error('boom!')
})
})

route.all(function handleError(err, req, res, next) {
return new Promise(function () {
throw new Error('oh, no!')
})
})

route.all(function handleError(err, req, res, next) {
return new Promise(function () {
res.statusCode = 500
res.end('caught: ' + err.message)
})
})

request(server)
.get('/foo')
.expect(500, 'caught: oh, no!', done)
})
})

describe('path', function () {
Expand Down

0 comments on commit 05eae10

Please sign in to comment.