事件发射器发射一次,请求挂起

EventEmiter Fire Once, Request Pends After

本文关键字:一次 请求 挂起 发射器 发射 事件      更新时间:2023-09-26

我正在尝试在这个平台上制作我的第一个应用程序时,用express访问nodejs。在图片上的这个代码上,我是来自帖子请求的,我正在尝试检查发送给我的userData是否已经注册。否则,它将注册用户。为了尽量减少回调,我将使用事件来告诉我调用的函数是否完成。在这种情况下,如果checkUser函数属性在图像的右侧,如果db找到了用户,它将发出写在左侧的userAuthenticated事件。如果不是,它将写入用户并发出userRegistered事件。

问题是,有时它有效,有时它不起作用。这是我第一次在node上编写异步函数,我对它的工作方式感到困惑。

  • 代码-http://prntscr.com/9h2qr2
  • 浏览器出错-http://prntscr.com/9h2szw
  • 节点中出错-http://prntscr.com/9h2t81

问题是在发送响应后没有删除事件处理程序。on()保留事件处理程序,直到它们被显式删除。因此,对于每个连接,都会添加新的事件处理程序,但从未删除。

即使您使用.once()而不是.on(),您仍然需要删除其他未激发事件的处理程序。

IMHO您最好只使用一个回调,而不是使用EventEmitter使事情复杂化。例如:

models/authenticate.js:

// ...
exports.checkUser = function(data, cb) {
  UsersDB.findOne({ fbid: data.id }, function(err, doc) {
    if (err)
      return cb(err);
    if (doc === null)
      insertUser(data, cb);
    else
      cb(null, 'Authenticated', doc);
  });
};
var insertUser = exports.insertUser = function(data, cb) {
  var insertData = {
    fbid: data.id
    first_name: data.first_name
    last_name: data.last_name,
    email: data.email,
    created_at: new Date()
  };
  UsersDB.insert(insertData, function(err, doc) {
    if (err)
      return cb(err);
    cb(null, 'Registered', doc);
  });
};

controllers/authenticate.js:

// ...
model.authenticate(req.body, function(err, action, data) {
  if (err)
    return res.json({ error: err });
  res.json({ action: action, userData: data });
});

此外,您可以简化"检查并插入"逻辑,使用MongoDB的"upstart"功能,该功能将为您执行这两个步骤,而不是两个单独的数据库调用。要了解如何做到这一点,请查看这个SO答案。