JavaScript 函数在使用 socket.io 作为回调传递给后端(节点)时未绑定“this”

javascript function is not binding the 'this' when passed as a callback to the backend(node) using socket.io

提问人:Alexander 提问时间:1/2/2023 更新时间:1/2/2023 访问量:75

问:

我在前端的一个功能是使用“this”。

function myFunction() {     
    ...     
    console.log(this);     
    ... 
}

我这样称呼它:

myFunction.call(objAsThis, param1, param2);

一切都按预期进行。但后来我尝试使用 socket.io 将此函数作为回调传递给后端(node.js):

客户

socket.emit("some event", param3, param4, myFunction);

以相同的方式在 node 中调用此函数会呈现一些意外结果。

服务器

socket.on("some event", function(param3, param4, myCbFunction) {     
    ...     
    myCbFunction.call(someObject, param5, param6);     
    ... 
});

我希望看到 someObject 对象被打印出来,但我却打印了 socket.io 的“this”。如果我尝试使用绑定,同样的故事:

myCbFunction.bind(someObject)(param5, param6);

我什至尝试(出于好奇)用new来称呼它,这应该创建一个新对象,但它没有。结果和以前一样。

new myCbFunction(param5, param6);

如果我只是在服务器上的“某个事件”事件处理程序中,我会得到相同的结果(socket.io 就是这样)。 因此,myCbFunction 完全忽略了调用、绑定调用console.log(this)

有人可以解释一下这是怎么回事吗?为什么它没有将其绑定到我提供的对象?

javascript 节点.js socket.io 回调 这个

评论

0赞 Alexander 1/2/2023
嗨@jfriend00感谢您的回复。socket.io 网站指出,您可以在客户端和服务器之间传递回调。socket.io/docs/v3/emitting-events/#acknowledgements .我会在早上添加更多信息,我现在的位置有点太晚了。

答:

1赞 jfriend00 1/2/2023 #1

好吧,我想我看到了一个混乱的根源。

在服务器上注册时:

socket.on("some event", function(param3, param4, callback) {     
    ...
    callback(someArgs);
});

重点是通知客户端您已收到消息。它在文档中称为函数。这不是直接调用您的客户端代码。事实上,这个回调函数是 socket.io 提供的东西,当你调用它时,你是在调用 socket.io,而不是调用客户端。 相反,您可以调用 socket.io 提供的此函数,当 socket.io 收到此函数调用时,它会打包一条消息,并通过 socket.io 连接将该消息发送回客户端。当您想要告诉客户端您已收到原始消息时,可以在服务器上调用该 ack 函数。callback()ack

请记住,客户端和服务器几乎总是位于相距数英里的不同计算机上(始终位于 TCP 套接字的对端)。不能直接从服务器调用客户端代码。

客户端 socket.io 代码将接收该 ack 消息(以及随它发送的任何可序列化参数),然后将调用您在此处指定的客户端 ack 函数:

socket.emit("some event", param3, param4, myFunction);

当调用此 ack 函数时,您无法控制该值 - 它将是 socket.io 设置的任何值(除非您将其声明为箭头函数)。但是,您可以使用存根函数,然后在调用实际函数之前重新附加所需的值,而不是传递实际函数。thisthis

socket.emit("some event", param3, param4, function(...args) {
     myFunction.call(objAsThis, ...args)
});

然后,这将忽略 socket.io 库传递给回调的值,并附加所需的值。你也可以用来做同样的事情:this.bind()

socket.emit("some event", param3, param4, myFunction.bind(objAsThis));

这只是传递存根函数的另一种方式,如前面的代码解决方案所示。

而且,如果在词法上下文中,您还可以使用箭头函数。this

评论

0赞 Alexander 1/3/2023
这实际上很酷,很有意义,我现在明白了。感谢您的回答!