使用后销毁 EventEmitter Listener

Destroy EventEmitter Listener after use

我不确定标题,但我想不出更好的标题。我的问题是,我试图避免连续太多回调,所以我使用了 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);
});

我第一次制作 post-request 时,一切正常,但是当我第二次尝试时,出现错误:

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

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

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

先谢谢大家了!

是的,当您第二次调用 post 时,您将再次为 "validated" 和 "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. 抱歉,您的示例代码真的很糟糕。事件发射器是很酷的模式,但不适用于这些东西。不要害怕回调,回调没那么可怕