【问题标题】:trying to understand a code fragment of an article on socket.io and redis试图理解socket.io和redis上一篇文章的代码片段
【发布时间】:2017-07-12 16:36:27
【问题描述】:

我正在尝试理解一篇文章here,现在一切都清楚了,只是一个代码片段,在前一个代码块中提到,总共1到17行,这个片段是从第1行到9:

app.use(function(req,res,next) {
   redis.get(req.user.email, function(err, id) {
     if (err) next(err);
      req.emitToUser = function() {
        var soc = id && io.to(id);
        soc.emit.apply(soc, arguments);
     }
  });
});

我认为它在我的 javascript 知识中的一些缺点是根本原因。 我对此代码片段的了解:

  • “apply”方法将执行“emit”,将“soc”作为“this”值 并用 'arguments' 提供 'emit' 方法(我就在这里吗? 请?)
  • socket.id 与套接字所有者的电子邮件有关,因为 id.to(id) 是基于 socket.id 是每个套接字与其自身连接的房间这一事实。 Redis提供了key-value数据结构,以用户email为key,value为socket.id。

问题:

  • “参数”从何而来?
  • 这段代码的用途是什么?

请说清楚。

【问题讨论】:

    标签: redis socket.io


    【解决方案1】:

    此代码存在一些问题,但总体思路是为每个传入请求在 req 对象 req.emitToUser() 上定义一个方法,这将允许链中稍后的一些其他路由处理程序使用该方法发出给提出请求的用户。这是希望将当前连接的 socket.io 连接连接到发出 http 请求的用户的常见愿望。

    让我们看看这里的每一行:

    redis.get(req.user.email, function(err, id) {
    

    在 redis 数据库中查找 req.user.email 以获取与该电子邮件相关联的 socket.io id,该电子邮件之前已保存在该 redis 数据库中。

    if (err) next(err);
    

    如果在 redis 中没有找到,让这个请求失败并报错。

    req.emitToUser = function() {
    

    为当前的req 对象分配一个新方法,以便链中后面的其他路由处理程序可以使用该方法。

     var soc = id && io.to(id);
    

    在 socket.io 中查找 id 值以获取该 id 的套接字。从技术上讲,io.to() 不会返回套接字,但它会返回一个您可以调用 emit() 的对象,该对象将发送到该套接字。

    soc.emit.apply(soc, arguments);
    

    soc.emit.apply(soc, arguments);的作用是这样的:

    1. 执行soc.emit()方法
    2. 在对soc 对象执行该方法时设置this 值。
    3. 在执行该方法时将参数设置为调用时传递给req.emitToUser(x, y, z) 的任何参数。

    这是一个更具体的例子:

    function fn(a, b, c) {
        console.log(a, b, c);
    }
    
    fn.apply(null, [1, 2, 3]);
    

    使用fn.apply(null, [1, 2, 3]); 将等同于:

    fn(1, 2, 3);
    

    现在,当参数已知时,您可能永远不会以这种确切的方式使用.apply()。使用它的情况是当您有一些任意数组传递给您时(您不知道其中有什么),并且您希望将这些参数以与提供给您的顺序完全相同的顺序传递给其他函数.这就是soc.emit.apply(soc, arguments); 正在做的事情。它采用arguments 对象(这是一个类似数组的结构,表示传递给父函数req.emitToUser() 的参数并将这些确切的参数传递给它sock.emit()。如果您确切知道会有多少参数,那么您可以硬编码与此相同的代码:

    app.use(function(req,res,next) {
       redis.get(req.user.email, function(err, id) {
         if (err) next(err);
          req.emitToUser = function(msg, data) {
            var soc = id && io.to(id);
            soc.emit(msg, data);
         }
      });
    });
    

    但是,.apply() 创建了一个更通用的解决方案,无论将多少参数传递给req.emitToUser(),它都可以正常工作,因为它只会将所有参数传递给soc.emit()


    这行代码有点可疑:

    var soc = id && io.to(id);
    

    它似乎试图防止之前没有从 redis 返回正确的 id。但是,如果没有 id,那么 soc 将不是一个有效的对象,下面类似的代码:

    soc.emit.apply(soc, arguments);
    

    会抛出。所以,id && io.to(id) 并没有真正提供适当的保护。看起来这更有可能是:

    app.use(function(req,res,next) {
       redis.get(req.user.email, function(err, id) {
         if (err) next(err);
          req.emitToUser = function() {
            if (id) {
                var soc = io.to(id);
                soc.emit.apply(soc, arguments);
            } else {
                // not sure what you want here, perhaps return an error
                // or throw a more meaningful exception
            }
         }
      });
    });
    

    【讨论】:

    • @AdrianDain - 这回答了你的问题吗?
    • @AdrianDain - 你为什么发布新问题,甚至没有在这里提供任何回复?就目前而言,感觉没有什么理由可以帮助你,因为你消失了两个星期,然后,即使你回来了,也不会对答案提供任何反馈。这就像试图帮助一堵砖墙——这就是我现在从你身上感受到的参与程度。这个地方是双向街道。你参与的越多,帮助你的人就越多。这不是一个开车问路的地方。提出问题,两周后回来。
    • @AdrianDain - 关键是您应该在此处做出响应(以小时为单位,而不是几周),并提供一些指示是否回答了您的问题。如果没有,那么请解释尚未回答的问题,以便我们完成这个问题。如果您的问题现已得到解答,那么您可以通过单击答案左侧的复选标记来向社区表明这一点,以“接受”它作为最佳答案并完成此问题。
    • @AdrianDain - 我在回答中为.apply() 添加了更多解释。以后如果您对答案中的某些内容不理解,请告诉我们您还不理解的内容。
    • 我删除了那些与页面主题无关的cmets,以免打扰其他读者。非常感谢您 100% 清楚的回复!事实上,我现在对为什么要使用“apply”以及我对 soc = id && io.to(id); 的困惑毫无疑问。 (我的主要问题)消失了。完美!
    猜你喜欢
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    • 2010-11-30
    • 1970-01-01
    相关资源
    最近更新 更多