问题
With a little help I've arrived at the following code to promisify a passport.js login strategy.
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var Promise = require('bluebird');
var bcrypt = require('bcrypt');
var db = require('./db').db; //users are stored in mongo
//I'm using bluebird.js for promises
var users = Promise.promisifyAll(db.users);
var compare = Promise.promisify(bcrypt.compare);
// This strategy is used by passport to handle logins
module.exports.localStrategy = new LocalStrategy(function(username, password, done) {
users.findOneAsync({username: username}).bind({})
.then(function(user) {
if (!user) {
throw new NoMatchedUserError('Incorrect username.');
//should be equivalent to:
// return done(null, false, {message:'something'});
}
this.user = user;
return compare(password, user.password);
})
.then(function(isMatch) {
if (isMatch) {
return this.user;
//is equivalent to:
// return done(null, this.user);
}
else {
throw { message: 'Incorrect password.' };
//should be equivalent to:
// return done(null, false, {message:'something else'};
}
})
.nodeify(done);
});
by calling nodeify(done) I can handle the path where passwords match but I don't know how to pass the optional third parameter out so that passport.js can use it.
Is it possible to have the two failure (not error) paths handled?
Update:
As asked in the comments I created an issue on Github and this feature was (very promptly) added in Bluebird v2.0
https://github.com/petkaantonov/bluebird/issues/219
回答1:
Currently, there is no way to do it with .nodeify
, you can of course do it manually with .then
:
.then(function(result){
done(/*whatever arguments you need*/);
},function(failure){
done(/* failure argumnets */);
});
回答2:
Use:
.nodeify(done, {spread: true});
This allows multiple arguments to be passed to the 'done' callback.
More info on:
Bluebird nodeify documentation
回答3:
I'm adding this answer to show how to use .nodeify(done, {spread: true})
(as mentioned in other answers/comments) with the original example.
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var Promise = require('bluebird');
var bcrypt = require('bcrypt');
var db = require('./db').db; //users are stored in mongo
//I'm using bluebird.js for promises
var users = Promise.promisifyAll(db.users);
var compare = Promise.promisify(bcrypt.compare);
// This strategy is used by passport to handle logins
module.exports.localStrategy = new LocalStrategy(function(username, password, done) {
users.findOneAsync({username: username}).bind({})
.then(function(user) {
if (!user) {
return [false, { message: 'Incorrect username.' }]; <---------------
//should be equivalent to:
// return done(null, false, {message:'something'});
}
this.user = user;
return compare(password, user.password);
})
.then(function(isMatch) {
if (isMatch) {
return this.user;
//is equivalent to:
// return done(null, this.user);
}
else {
return [false, { message: 'Incorrect password.' }]; <---------------
//should be equivalent to:
// return done(null, false, {message:'something else'};
}
})
.nodeify(done, {spread: true});
});
来源:https://stackoverflow.com/questions/23920589/how-to-pass-a-third-argument-to-a-callback-using-bluebird-js-nodeify