Skip to content

Commit

Permalink
Merge 34aaf61 into 7c86f19
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbayo10 committed Mar 30, 2018
2 parents 7c86f19 + 34aaf61 commit 2c72577
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 3 deletions.
33 changes: 30 additions & 3 deletions lib/layer.js
Expand Up @@ -66,7 +66,9 @@ Layer.prototype.handle_error = function handle_error(error, req, res, next) {
}

try {
fn(error, req, res, next)
var result = fn(error, req, res, next)

handlePromise(result, next)
} catch (err) {
next(err)
}
Expand All @@ -90,7 +92,9 @@ Layer.prototype.handle_request = function handle(req, res, next) {
}

try {
fn(req, res, next)
var result = fn(req, res, next)

handlePromise(result, next)
} catch (err) {
next(err)
}
Expand Down Expand Up @@ -141,7 +145,7 @@ Layer.prototype.match = function match(path) {
var keys = this.keys
var params = this.params

for (var i = 1; i < match.length; i++) {
for (var i = 1 i < match.length i++) {
var key = keys[i - 1]
var prop = key.name
var val = decode_param(match[i])
Expand Down Expand Up @@ -178,3 +182,26 @@ function decode_param(val){
throw err
}
}

function handlePromise(promise, next) {
var isPromise = checkPromise(promise)

if (!isPromise) {
return
}

promise.then(null, function (err) {
next(err || new Error('Empty promise rejection'))
})
}

/**
* Returns true if val is a promise
*
* @param {any} val
* @return {boolean}
* @private
*/
function checkPromise(val) {
return !!val && (typeof val === 'object' || typeof val === 'function') && typeof val.then === 'function'
}
86 changes: 86 additions & 0 deletions test/router.js
Expand Up @@ -124,6 +124,92 @@ describe('Router', function () {
.expect(404, cb)
})

it('should support promise as route handler', function (done) {
if (!global.Promise) {
return done();
}

var router = new Router()
var server = createServer(router)

router.all('/:thing', function (req, res) {
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve()
}, 100);
});

promise
.then(function () {
saw(req, res)
})

return promise
})

router.use(function (err, req, res, next) {
res.sendStatus(500)
})

request(server)
.get('/foo')
.expect(200, 'saw GET /foo', done)
})

it('should support catch rejected promise', function (done) {
if (!global.Promise) {
return done();
}

var router = new Router()
var server = createServer(router)

router.all('/:thing', function (req, res) {
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject();
}, 100);
});

return promise
})

router.use(function (err, req, res, next) {
res.sendStatus(500)
})

request(server)
.get('/foo')
.expect(500, done)
})

it('should support catch rejected promise with error', function (done) {
if (!global.Promise) {
return done();
}

var router = new Router()
var server = createServer(router)

router.all('/:thing', function (req, res) {
var promise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error('async request failed'));
}, 100);
});

return promise
})

router.use(function (err, req, res, next) {
res.sendStatus(500)
})

request(server)
.get('/foo')
.expect(500, done)
})

it('should not stack overflow with many registered routes', function (done) {
var router = new Router()
var server = createServer(router)
Expand Down

0 comments on commit 2c72577

Please sign in to comment.