javascript - 除非全局声明,否则无法从事件处理程序内的函数更新变量

标签 javascript node.js mongoose scope socket.io

我有一个nodejs后端应用程序,它利用mongoose进行数据库连接和查询,在本例中,它在socket.io的事件处理程序中执行,即 io.on("connection", [callback])

但是,每当我在 io.on("connection") 的事件处理程序中运行查询时,例如socket.on("myEvent", [callback])我在更新后一个事件处理程序中的变量时遇到问题 - 具体来说,当它是 Mongoose 查询的回调时。

对于某些上下文,以下是我尝试运行的示例:

io.on("connection", function(socket) {
  var myVar; // declare user within event handler scope
  socket.on("myEvent", function(m) {
    var query = m.myQuery;
    User.findOne({query}, function(err, doc) {
    if (err) {
      // error handling
    } else {
      myVar = doc;
      console.log(myVar); // logs whole document as it should
    }
  });

  socket.on("myOtherEvent", function(m){
    console.log(myVar); // undefined!?
  });
});

我还尝试在自己的函数上使用自定义回调来解决此问题,该函数运行相同的查询并返回文档,因为我认为这可能是由数据库查询异步引起的 - 然而,这种方法并没有也不工作。

此外,我尝试使用(显然是臭名昭著的)var that = this socket.on("myEvent)中的方法方法希望它引用原始回调。这部分也不走运。

要么我错过了 Mongoose 的全部要点,要么我快疯了;帮助将不胜感激!

编辑:正如之前评论的,一旦我全局声明 myVar变量在 else 中更新所述 Mongoose 查询的 block 。然后我可以通过其他 socket.on 访问它处理程序也是如此。

我应该在 socket.on("connection") 中声明我的变量吗?阻止它保持不变,例如如果我console.log(myVar)声明myVar = "why isn\'t this working?!"socket.on("myOtherEvent")内它实际上记录 "why isn't this working?!"到控制台

编辑 2:此处描述了一个非常相似的问题:Node, Mongoose - Can't access parent scope in query callback

使用myVar = myVar || {}的解决方案然而,没有工作。

编辑 3:按照建议,我使用(在本例中为 ES6)Promises 进行查询,更新后的查询(仍在 socket.on 内,只是未显示在此处)如下例所示基于它制作:

User.findOne({query}).exec().then(function(doc) {
    if (!doc) {
        myVar = null; // unrelated
        logger.debug("Couldnt find user!"); // unrelated
    } else {
        myVar = doc;
        logger.debug(doc); // correctly prints the whole document
        logger.debug(user); // also correctly prints whole document
    }
}).catch(function(err){
    logger.error("Error searching for query: " + err);// unrelated
});

就目前情况而言,我是否应该稍后尝试访问 myVar (查询完成并将文档打印到控制台后,在 else block 内)它仍然打印出我赋予它的初始值。无论是 null、 bool 值还是字符串 - 它都保持不变。

但是:值得注意的是,如果我全局声明它,它就会开始更新变量 - 但是,它并不是套接字所独有的,这就是为什么这种方法不起作用的原因对于这个具体问题

最佳答案

最初由@Bergi解决 - 谢谢!

对于任何新手或不知道(就像我一样)套接字连接无法合并的人:

与此问题具体相关的是 Socket.io 创建多个实例/处理程序 - 具体来说,每个套接字一个。 这意味着拥有多个套接字连接将使用所述事件处理程序创建多个实例,这也会导致这些变量的多个实例。

例如,如果您出于某种原因想要拥有特定于每个套接字连接的本地作用域变量,这也可能非常有用。

谢谢!

关于javascript - 除非全局声明,否则无法从事件处理程序内的函数更新变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47318425/

相关文章:

javascript - mongodb中如何按多个字段聚合

MongoDB $slice(嵌入式数组分页)

javascript - 从 mongodb 回调将值设置为外部变量

javascript - 用于检测浏览器版本的 XML/Javascript

javascript - 为什么箭头函数作为静态成员值没有词法范围?

node.js - 来自服务器 : * OK The Microsoft Exchange IMAP4 service is ready 的无效问候

node.js - 我可以在 CentOS 6x 上安装 nodejs v.8.12 吗?

javascript - 当我触发一个事件时,它会被触发几次而不是在 jQuery 中输入一次

javascript - 如何通过一个函数实时验证表单中的多个元素(例如名称、城市和州)?

javascript - 以最有效的方式更新许多(100k+)文档 MongoDB