问题
When using the waterline ORM, if I want to consume the bluebird promise api thats shipped by default how to I pass the processing back to the controller.
Below is the code :
module.exports = {
//Authenticate
auth: function (req, res) {
user = req.allParams();
//Authenticate
User.authenticate(user, function (response) {
console.log(response);
if (response == true) {
res.send('Authenticated');
} else {
res.send('Failed');
}
});
}
};
module.exports = {
// Attributes
// Authenticate a user
authenticate: function (req, cb) {
User.findOne({
username: req.username
})
.then(function (user) {
var bcrypt = require('bcrypt');
// check for the password
bcrypt.compare(req.password, user.password, function (err, res) {
console.log(res);
if (res == true) {
cb(true);
} else {
cb(false);
}
});
})
.catch(function (e) {
console.log(e);
});
}
};
I am simply trying to implement a authentication function. The business logic is straight forward. What I am confused of is how the request flow is handed back to the controller since. The promise doesn't respond if I try to return a response, but doing a cb(value) works.
回答1:
The key to working with promises is to never break the chain. A promise chain depends on every step either returning a promise or a value, or throwing an error.
The following is a rewrite of your code. Note that
- Every callback in the path returns something and every function returns the promise chain it works with (even
.auth()
; it might be useful at some point) - I've used BlueBird's
.promisifyAll()
to makebcrypt
play along - I've decoupled
.authenticate()
from your request/response infrastructure by making theusername
andpassword
arguments explicit. This way it can be reused more easily.
So now we have (not 100% tested, I did not bother installing waterline):
module.exports = {
// authenticate the login request
auth: function (req, res) {
var params = req.allParams();
return User.authenticate(params.username, params.password)
.then(function () {
res.send('Authenticated');
})
.fail(function (reason) {
res.send('Failed (' + reason + ')');
});
}
};
and
var Promise = require("bluebird");
var bcrypt = Promise.promisifyAll(require('bcrypt'));
module.exports = {
// check a username/password combination
authenticate: function (username, password) {
return User.findOne({
username: username
})
.then(function (user) {
return bcrypt.compareAsync(password, user.password)
})
.catch(function (err) {
// catch any exception problem up to this point
console.log("Serious problem during authentication", err);
return false;
})
.then(function (result) {
// turn `false` into an actual error and
// send a less revealing error message to the client
if (result === true) {
return true;
} else {
throw new Error("username or password do not match");
}
});
}
};
来源:https://stackoverflow.com/questions/30659272/sailsjs-waterline-with-bluebird-promises