[英]Is Socket.io “connect” event even safe to listen to?
I've been skeptical about this for years. 我对此一直持怀疑态度。 The common practice is making a Socket
and then listening to its "connect"
event. 常见的做法是制作一个Socket
, 然后侦听其"connect"
事件。 It doesn't sound very safe. 听起来不是很安全。
import io from "socket.io-client";
CONNECT: const socket = io(……);
// ← An asynchronous connection establishment might happen here, no?
LISTEN: socket.on("connect", ……);
It tries to establish a connection as soon as the CONNECT
statement gets executed. 一旦 CONNECT
语句被执行,它将尝试建立连接。 What if it does, before LISTEN
? 如果可以, 在 LISTEN
之前怎么办?
What makes such a practice safe to be used? 是什么使这种做法可以安全使用? What I believe is that just because it is two consecutive statements doesn't mean an asynchronous connection establishment cannot happen in-between. 我相信,仅仅因为它是两个连续的语句,并不意味着异步连接建立不会在两者之间发生。 Are my thoughts wrong? 我的想法错了吗?
I've just read the source code of socket.io-client
and drawn a conclusion that the only code-wise safe way to go is to turn the autoConnect
option off for io()
not to create a Socket
that automatically tries to establish a connection, which leads to arbitrary (“possibly-untimely”) emission of the "connect"
event. 我刚刚阅读了socket.io-client
的源代码,并得出了一个结论,即代码上唯一安全的方法是关闭io()
的autoConnect
选项,而不是创建一个自动尝试建立Socket
连接,导致任意(“可能不及时”)发出"connect"
事件。 This requires a manual call to socket.open()
but is safe. 这需要手动调用socket.open()
但很安全。
Here's how it goes: 这是怎么回事:
io()
creates a Manager
instance and calls .socket()
of it . io()
创建一个Manager
实例并调用.socket()
。
The .socket()
creates a new Socket
instance and then binds the Manager
's own internal handlers (that is not users') for "connecting"
and "connect"
events . .socket()
创建一个新的Socket
实例 , 然后为"connecting"
和"connect"
事件绑定Manager
自己的内部处理程序(不是用户的) 。
Since the Socket
's constructor .open()
s if autoConnect
, which involves the immediate emission of a "connecting"
event and the future emission of a "connect"
event , the Manager
calls its own internal "connecting"
event handler manually if autoConnect
. 由于Socket
的构造函数.open()
如果为autoConnect
,则涉及立即发出"connecting"
事件以及将来发出"connect"
事件 ,因此如果使用autoConnect
,则Manager
将手动调用其内部的"connecting"
事件处理程序 。
new Socket
never waits for you 原来是new Socket
从来没有等你 I could not find any safe-guard gizmo (at least code-wise ) to keep an autoConnect
-ing Socket
from establishing a "connect"
-ion until corresponding handlers get attached. 我找不到任何安全的小控件(至少在代码方面是如此 ),以防止autoConnect
-ing Socket
建立"connect"
-ion,直到"connect"
相应的处理程序为止。
What's funny is that even Manager
does this dangerous practice, 有趣的是,即使是Manager
也进行了这种危险的做法,
Manager.prototype.socket = function (nsp, opts) {
var socket = this.nsps[nsp];
if (!socket) {
socket = new Socket(this, nsp, opts);
this.nsps[nsp] = socket;
var self = this;
socket.on('connecting', onConnecting);
socket.on('connect', function () {
socket.id = self.generateId(nsp);
});
if (this.autoConnect) {
// manually call here since connecting event is fired before listening
onConnecting();
}
}
function onConnecting () {
if (!~indexOf(self.connecting, socket)) {
self.connecting.push(socket);
}
}
return socket;
};
making an assumption that a Socket
, with the autoConnect
option being true
or not, 假设Socket
和autoConnect
选项为true
,
socket = new Socket(this, nsp, opts);
won't get to "connect"
before 之前不会"connect"
socket.on('connect', function () {
socket.id = self.generateId(nsp);
});
. 。
Are there any good reasons to make this assumption, aside from “the code path to handler-attaching just looks shorter (“cheaper”) than that of connection establishment?” How come this is not a race condition ? 除了“到处理程序附加的代码路径看起来比连接建立的路径看起来更短(“便宜”)之外,是否有充分的理由进行此假设?”这怎么不是竞争条件呢?
You need an EventEmitter before to attach a connect
event, additionally the socket.io-client library manages this scenario, take a look on: 在附加connect
事件之前,您需要一个EventEmitter,另外,socket.io-client库管理这种情况,请看一下:
https://github.com/socketio/socket.io-client/blob/master/lib/manager.js#L378 https://github.com/socketio/socket.io-client/blob/master/lib/manager.js#L378
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.