【问题标题】:Adding a variable to sockets in socket.io在 socket.io 中向套接字添加变量
【发布时间】:2016-10-05 17:31:15
【问题描述】:

我想将一个名为player 的对象关联到不同的套接字。所以我认为最简单的方法就是socket.prototype.player = whatever;

但是,无论我尝试制作什么原型,我都无法定义。任何人都知道如何做到这一点?如果这是不好的做法,也是 IDK。告诉我。

【问题讨论】:

  • 它可能“只是”一个对象,所以尝试使用socket.player = whatever
  • 我认为我们需要看看您的代码是否还有更多内容。您还使用客户端socket.io吗?如果是这样,您的发射在服务器中是什么样的?

标签: javascript node.js socket.io


【解决方案1】:

您还可以像这样处理在线用户将他们与他们的套接字 id 配对

io.on('connection', function(socket){
  socket.on('disconnect', function() {
    console.log("disconnect")
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].socket === socket.id){
        console.log(onlineplayers[i].code + " just disconnected")
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_join', function(player) {
    if(player.available === false) return
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        exists = true
      }
    }
    if(exists === false){
      onlineplayers.push({
        code: player.code,
        socket:socket.id
      })
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_leave', function(player) {
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })
})

【讨论】:

    【解决方案2】:

    由于您确实询问了最佳做法,因此不建议修改不受您控制的类型的原型或在其之上使用自定义变量。虽然 JavaScript 相当松散并且允许您进行这些更改,但您应该防范 Socket.IO 将来可能对原型进行任何进一步的更改。

    原因是总是有可能与您使用的任何属性名称发生冲突,无论多么小。

    为了解决这个问题,我们可以使用与套接字 ID 相关的 Map,或者在套接字本身上使用 Wea​​kMap。如果您使用 Map,则必须在套接字断开连接时手动删除该条目,但使用 Wea​​kMap,它会自动进行垃圾收集(假设 SocketIO 在断开连接时释放对它的所有引用)。

      /** @type {WeakMap<SocketIO.Socket, Object>} */
      const socketIOLocals = new WeakMap();
      io.use((socket, next) => {
          const locals = { player: null }; // Create new instance
          socketIOLocals.set(socket, locals);
          next();
      });
    

    然后就可以用socketIOLocals.get(socket)获取变量对象了;


    附带说明,Express 确实具有.locals 属性,可让您在Response 对象之间传递数据。可惜 SocketIO 没有这样的东西。

    【讨论】:

      【解决方案3】:

      截至 2017 年 12 月的解决方案(socket.io 内部变化比人们想象的要频繁)。在这个版本中,我创建了一个 join_exclusive 函数,它将离开所有房间,除了默认房间和您要加入的新房间

      io.sockets.on('connection', function(socket) {
          socket.join_exclusive = function (newroom) {
              for (var room in this.manager.roomClients[this.id]) {
                  if (room == '') continue; // default room required for socket.emit(...
                  this.leave(room.slice(1)); // remove '/' char
              }
              this.join(newroom);
          };
      });
      

      【讨论】:

        【解决方案4】:

        socket.io socket 只是一个 Javascript 对象。您可以直接向其中添加任何属性,而不是通过原型。

        因此,在服务器上,您可以直接向socket 对象添加一个新属性:

        io.on('connection', function(socket) {
            // some code to get the name for this user
            var name = .....
            socket.player = name;
        });
        

        此类属性不与连接的另一端共享 - 它们是该特定对象的本地属性,并且仅在连接的这一端可用。

        【讨论】:

        • 谢谢老哥,你就像一个该死的忍者O_O,或者我真的很慢......让我们去前者
        猜你喜欢
        • 1970-01-01
        • 2015-07-18
        • 1970-01-01
        • 1970-01-01
        • 2011-06-07
        • 2014-04-19
        • 1970-01-01
        • 2014-12-24
        • 2014-10-14
        相关资源
        最近更新 更多