Skip to content

Commit

Permalink
next() returns a promise
Browse files Browse the repository at this point in the history
  • Loading branch information
calebmer committed Oct 23, 2015
1 parent 62277a8 commit 25b8f23
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 6 deletions.
25 changes: 22 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ var parseUrl = require('parseurl')
var Route = require('./lib/route')
var setPrototypeOf = require('setprototypeof')

var Promise = typeof global.Promise == 'function' ?
global.Promise :
require('es6-promise').Promise

/**
* Module variables.
* @private
Expand Down Expand Up @@ -186,6 +190,17 @@ Router.prototype.handle = function handle(req, res, callback) {
req.baseUrl = parentUrl
req.originalUrl = req.originalUrl || req.url

// promise that resolves when either the next chain finishes, or a response is sent
var requestComplete = new Promise(function (resolve, reject) {
done = wrap(done, function (fn, err) {
if (err) {
reject(err)
}
resolve()
defer(fn, err)
})
})

next()

function next(err) {
Expand All @@ -209,14 +224,15 @@ Router.prototype.handle = function handle(req, res, callback) {
// no more matching layers
if (idx >= stack.length) {
defer(done, layerError)
return
return requestComplete
}

// get pathname of request
var path = getPathname(req)

if (path == null) {
return done(layerError)
done(layerError)
return requestComplete
}

// find next matching layer
Expand Down Expand Up @@ -266,7 +282,8 @@ Router.prototype.handle = function handle(req, res, callback) {

// no match
if (match !== true) {
return done(layerError)
done(layerError)
return requestComplete
}

// store route for dispatch on change
Expand All @@ -292,6 +309,8 @@ Router.prototype.handle = function handle(req, res, callback) {

trim_prefix(layer, layerError, layerPath, path)
})

return requestComplete
}

function trim_prefix(layer, layerError, layerPath, path) {
Expand Down
2 changes: 1 addition & 1 deletion lib/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,6 @@ function once(fn) {
called = true
}

fn.call(this, err)
return fn.call(this, err)
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"dependencies": {
"array-flatten": "1.1.1",
"debug": "~2.2.0",
"es6-promise": "^3.0.2",
"methods": "~1.1.1",
"parseurl": "~1.3.0",
"path-to-regexp": "0.1.7",
Expand All @@ -16,7 +17,6 @@
},
"devDependencies": {
"after": "0.8.1",
"bluebird": "2.10.2",
"finalhandler": "0.4.0",
"istanbul": "0.3.17",
"mocha": "2.2.5",
Expand Down
110 changes: 109 additions & 1 deletion test/promise.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@

var Router = require('..')
var utils = require('./support/utils')
var Promise = require('bluebird')
var after = require('after')
var Promise = require('es6-promise').Promise

var assert = utils.assert
var createHitHandle = utils.createHitHandle
var createErrorHitHandle = utils.createErrorHitHandle
var shouldHitHandle = utils.shouldHitHandle
var shouldNotHitHandle = utils.shouldNotHitHandle
var createServer = utils.createServer
var request = utils.request

Expand Down Expand Up @@ -85,4 +87,110 @@ describe('Promise', function () {
.expect(shouldHitHandle(3))
.expect(200, done)
})

describe('from next', function () {
it('will be returned', function (done) {
var router = Router()
var server = createServer(router)
done = after(2, done)

router.use(createHitHandle(1))

router.use(function (req, res, next) {
var result = next()
assert(result.then, 'next() is thenable')
done()
})

router.use(createHitHandle(2))

router.use(function (req, res) {
res.end('done')
})

request(server)
.get('/')
.expect(shouldHitHandle(1))
.expect(shouldHitHandle(2))
.expect(200, 'done', done)
})

it('will resolve when all handles are done', function (done) {
var router = Router()
var server = createServer(router)
done = after(2, done)

router.use(createHitHandle(1))

router.use(function (req, res, next) {
return next().then(function () {
res.end('done')
done()
})
})

router.use(createHitHandle(2))

request(server)
.get('/')
.expect(shouldHitHandle(1))
.expect(shouldHitHandle(2))
.expect(200, 'done', done)
})

it('can be used as an alternate error handler', function (done) {
var router = Router()
var server = createServer(router)
done = after(2, done)

router.use(createHitHandle(1))

router.use(function (req, res, next) {
return next().catch(function (err) {
assert(err.message.match(/some error/i), 'Catches correct error')
res.end('done')
done()
})
})

router.use(createHitHandle(2))
router.use(function (req, res, next) { next(new Error('Some error')) })
router.use(createErrorHitHandle(3))

request(server)
.get('/')
.expect(shouldHitHandle(1))
.expect(shouldHitHandle(2))
.expect(shouldHitHandle(3))
.expect(200, 'done', done)
})

it('will not resolve if the stack is not exhausted', function (done) {
var router = Router()
var server = createServer(router)

router.use(createHitHandle(1))

router.use(function (req, res, next) {
return next().then(function () {
done(new Error('This should never be called'))
})
})

router.use(createHitHandle(2))

router.use(function (req, res) {
res.end('done')
})

router.use(createHitHandle(3))

request(server)
.get('/')
.expect(shouldHitHandle(1))
.expect(shouldHitHandle(2))
.expect(shouldNotHitHandle(3))
.expect(200, 'done', done)
})
})
})

0 comments on commit 25b8f23

Please sign in to comment.