使用后销毁EventEmitter侦听器

时间:2015-01-12 22:48:29

标签: node.js eventemitter

我不确定标题,但我想不出更好的标题。我的问题是,我试图连续避免过多的回调,所以我使用了EventEmitter。 我在模块中有一个函数,它检查给定的用户名和密码是否与数据库条目匹配:

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;

我在我的一条路线中调用此功能:

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);
});

我第一次发布请求后,一切正常,但是当我第二次尝试时,我收到错误:

http.js:690
throw new Error('Can\'t set headers after they are sent.');

我认为,在第二个请求期间,节点使用与之前相同的侦听器,因此导致错误的响应对象相同。

我的问题是:我该如何避免这种情况?

提前谢谢你们!

1 个答案:

答案 0 :(得分:1)

是的,当您第二次拨打电话时,您正在添加"已验证"并且" notValidated"事件再次(并在第三次你将再次添加等等...)。您可以使用事件发射器的once方法来避免此问题:

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

  1. 要删除事件侦听器,您可以使用removeListener方法

  2. 抱歉,您的示例代码非常糟糕。事件发射器是很酷的模式,但不是这个东西。不要害怕回电,他们不是那么可怕。