I am not sure with the title, but I couldn't think of a better one. My problem is, that I tried to avoid too much callbacks in a row, so I used the EventEmitter. I have a function inside a module, that checks if a a given username and password match a database entry:
var PasswordChecker = function () {
events.EventEmitter.call(this);
var _self = this;
this.checkPassword = function (username,password) {
_self.emit( "findOne",username,password );
};
var _findOne = function (username,password) {
UserSchema.findOne({'username': username}, function (err, result) {
if (!err && result.username === username) {
_self.emit("passwordCheck", password, result.password);
} else {
_self.emit("notValidated");
}
});
};
var _passwordCheck = function (password, res_password) {
bcrypt.compare(password,res_password, function (err, res) {
if (err){
_self.emit("notValidated");
} else {
_self.emit("validated")
}
});
};
_self.on("findOne", _findOne);
_self.on("passwordCheck",_passwordCheck);
};
util.inherits(PasswordChecker,events.EventEmitter);
module.exports.PasswordChecker = new PasswordChecker;
And I call this function inside one of my routes:
router.post('/checkPassword', function(req, res){
user.PasswordChecker.on("validated", function () {
console.log("Validated");
res.status(200).send({success:true});
});
user.PasswordChecker.on("notValidated", function () {
console.log("notValidated");
res.status(400).send({success:false});
})
user.PasswordChecker.checkPassword(req.body.username, req.body.password);
});
The first time I make the post-request, everything works fine, but when I try it a second time, I get the error:
http.js:690
throw new Error('Can\'t set headers after they are sent.');
I think, that during the second request, node is using the same listener as before and therefore the same response object which causes the error.
My question is: How can I avoid this?
Thank you guys in advance!
Yes, when you're calling post for the second time, you are adding listeners for "validated" and "notValidated" events again (And at the third time you will add them again and so on..). You can use the once method of event emitter to avoid this problem:
user.PasswordChecker.once("validated", function () {
console.log("Validated");
res.status(200).send({success:true});
});
user.PasswordChecker.once("notValidated", function () {
console.log("notValidated");
res.status(400).send({success: false});
});
PS
To remove event listener, you can use removeListener methods
Sorry, but code of your example is really bad. Event emitter is cool pattern, but not for this stuff. Don't afraid of callbacks, they aren't so terrible.