-
-
Notifications
You must be signed in to change notification settings - Fork 103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add promise support #25
Changes from 4 commits
cc43534
f5a6145
3e5be32
3a925d6
3a21cd3
07a227f
08551f1
1a6f581
f97b229
1f312b3
79a4ee0
a7814d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,31 @@ function Layer(path, options, fn) { | |
} | ||
} | ||
|
||
/** | ||
* Handle any request for the layer. | ||
* | ||
* @api private | ||
*/ | ||
|
||
Layer.prototype._handle_any = function _handle_any(/* ...args, next */) { | ||
var self = this | ||
var next = arguments[arguments.length - 1] | ||
var handle = this.handle | ||
var result | ||
var hasNextBeenCalled = function () { return next._currentLayer === self } | ||
|
||
try { | ||
result = handle.apply(undefined, arguments) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prior to this change, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dougwilson If I understand, this will still function the same as this is already under strict mode. Also, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did some basic research and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi guys, what determines the context in this case is the strict mode of the You can see this displayed right here:
This right now is definitely a breaking point of this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, changed function strict() {
'use strict';
context.fn();
}
function sloppy() {
context.fn();
}
var context = {
a: 1,
fn: function () {
console.log(this.a);
console.log((function () { return !!this })());
}
};
strict();
sloppy(); and output:
Although I'm getting a different result from you (as you can see), both are returning the global object implying the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @calebmer , your change does not fix it, because the Your test above is also very different from the test I gave, as the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basically, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so I created a test for this, so really, all that would matter if the following test passed (ensure nowhere else in the file with the tests there is a describe('this', function () {
describe('when middleware is sloppy', function () {
it('should have global context', function (done) {
var router = new Router()
var server = createServer(router)
router.get('/', function (req, res) {
res.end(String(this === global))
})
request(server)
.get('/')
.expect(200, 'true', done)
})
})
describe('when middleware is strict', function () {
it('should have null context', function (done) {
'use strict'
var router = new Router()
var server = createServer(router)
router.get('/', function (req, res) {
res.end(String(this === global))
})
request(server)
.get('/')
.expect(200, 'false', done)
})
})
}) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the tests verbatim and they worked with both |
||
} catch (err) { | ||
return next(err) | ||
} | ||
|
||
if (result != null && typeof result.then === 'function') { | ||
var onRejected = function (error) { if (!hasNextBeenCalled()) { next(error) } } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a note, but we should probably use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added an error, but maybe someone would want to |
||
result.then(null, onRejected) | ||
} | ||
} | ||
|
||
/** | ||
* Handle the error for the layer. | ||
* | ||
|
@@ -58,18 +83,12 @@ function Layer(path, options, fn) { | |
*/ | ||
|
||
Layer.prototype.handle_error = function handle_error(error, req, res, next) { | ||
var fn = this.handle | ||
|
||
if (fn.length !== 4) { | ||
if (this.handle.length !== 4) { | ||
// not a standard error handler | ||
return next(error) | ||
} | ||
|
||
try { | ||
fn(error, req, res, next) | ||
} catch (err) { | ||
next(err) | ||
} | ||
this._handle_any(error, req, res, next) | ||
} | ||
|
||
/** | ||
|
@@ -82,18 +101,12 @@ Layer.prototype.handle_error = function handle_error(error, req, res, next) { | |
*/ | ||
|
||
Layer.prototype.handle_request = function handle(req, res, next) { | ||
var fn = this.handle | ||
|
||
if (fn.length > 3) { | ||
if (this.handle.length > 3) { | ||
// not a standard request handler | ||
return next() | ||
} | ||
|
||
try { | ||
fn(req, res, next) | ||
} catch (err) { | ||
next(err) | ||
} | ||
this._handle_any(req, res, next) | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
|
||
var Router = require('..') | ||
var utils = require('./support/utils') | ||
var Promise = require('bluebird') | ||
|
||
var assert = utils.assert | ||
var createServer = utils.createServer | ||
var request = utils.request | ||
|
||
describe('Promise', function () { | ||
it('rejecting will trigger error handlers', function (done) { | ||
var router = Router() | ||
var server = createServer(router) | ||
|
||
router.use(function (req, res) { | ||
return new Promise(function (resolve, reject) { | ||
reject(new Error('Happy error')) | ||
}) | ||
}) | ||
|
||
request(server) | ||
.get('/') | ||
.expect(500, done) | ||
}) | ||
|
||
it('will be ignored if next is called', function (done) { | ||
var router = Router() | ||
var server = createServer(router) | ||
var count = 0 | ||
|
||
router.use(function (req, res, next) { | ||
count++ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than asserting counts with a bunch of closures, please use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The count method I have found especially useful at places like L36 where I can test a closure has not been called. Is there a way to do this with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case, simply call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed the tests, also created a |
||
return new Promise(function (resolve, reject) { | ||
count++ | ||
next() | ||
setTimeout(function () { | ||
count++ | ||
resolve() | ||
}, 5) | ||
}) | ||
}) | ||
|
||
router.use(function (req, res) { | ||
assert.equal(count, 2) | ||
res.end('Awesome!') | ||
}) | ||
|
||
request(server) | ||
.get('/') | ||
.expect(200, done) | ||
}) | ||
|
||
it('can be used in error handlers', function (done) { | ||
var router = Router() | ||
var server = createServer(router) | ||
var count = 0 | ||
|
||
router.use(function (req, res, next) { | ||
count++ | ||
next(new Error('Happy error')) | ||
}) | ||
|
||
router.use(function (error, req, res, next) { | ||
count++ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than asserting counts with a bunch of closures, please use the |
||
return new Promise(function (resolve, reject) { | ||
count++ | ||
setTimeout(function () { | ||
count++ | ||
next(error) | ||
resolve() | ||
}, 5) | ||
}) | ||
}) | ||
|
||
router.use(function () { | ||
done(new Error('This should never be reached')) | ||
}) | ||
|
||
router.use(function (error, req, res, next) { | ||
assert.equal(count, 4) | ||
res.end('Awesome!') | ||
}) | ||
|
||
request(server) | ||
.get('/') | ||
.expect(200, done) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than assigning an anonymous function to a variable, just change this to a named function declaration. This means that runtime will have one less variable initialization + assignment and also an error occurring within the function for whatever reason will have the function's name in the stack trace instead of it being anonymous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best case scenario the fix in #26 means we don't need this. But I'll definitely fix if we do.