将自定义方法分配给 WebSocket 时如何避免竞争条件?
How to avoid race conditions when assigning custom methods to WebSocket?
当我查看有关 WebSockets 的 tutorials/documentation 时,我发现类似 this:
的代码
var ws = new WebSocket("ws://localhost:8765/dlt");
ws.onopen = () => {
// do some very important stuff after connection has been established
console.log("onopen");
}
但是这里的竞争条件呢?在 JavaScript 中是否以某种方式避免了?
例如此代码(仅在 连接打开后分配 onopen
)将失败:
var ws = new WebSocket("ws://localhost:8765/dlt");
setTimeout(() => {
ws.onopen = () => {
// do some very important stuff after connection has been established
console.log("onopen"); /// <== won't be called
}
}, 100);
我可以确定在连接建立之前分配已经完成吗?
(我尝试使用自定义 onopen()
方法扩展 WebSocket
,但这似乎不起作用)
class MyWebSocket extends WebSocket {
onopen() {
console.log("onopen()");
/// do some very important stuff after connection has been established
}
}
你放心,这个例子没问题。 Javascript 事件循环将在承担任何其他任务之前完成当前任务。这意味着 1) WebSocket 无法在 onopen
事件之前打开连接(异步操作),2) onopen
事件处理程序将在以下周期中被调用。
另一方面,设置超时会使事情复杂化,因为事件将在当前任务之后按某种顺序调用。这意味着 WebSocket 有机会在设置处理程序之前打开连接。
你应该读一读 javascript 的事件循环:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop
如果您查看有关 Run-to-completion
的部分,您会得到以下有用的解释:
Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.
因此在您的示例中,对 ws.onopen
的赋值必须在 websocket 执行本质上异步的任何操作之前完成。通过将您的分配放在 setTimeout
内,您将它移出当前 运行 上下文,因此它可能不会在 websocket 需要它之前执行。
当我查看有关 WebSockets 的 tutorials/documentation 时,我发现类似 this:
的代码var ws = new WebSocket("ws://localhost:8765/dlt");
ws.onopen = () => {
// do some very important stuff after connection has been established
console.log("onopen");
}
但是这里的竞争条件呢?在 JavaScript 中是否以某种方式避免了?
例如此代码(仅在 连接打开后分配 onopen
)将失败:
var ws = new WebSocket("ws://localhost:8765/dlt");
setTimeout(() => {
ws.onopen = () => {
// do some very important stuff after connection has been established
console.log("onopen"); /// <== won't be called
}
}, 100);
我可以确定在连接建立之前分配已经完成吗?
(我尝试使用自定义 onopen()
方法扩展 WebSocket
,但这似乎不起作用)
class MyWebSocket extends WebSocket {
onopen() {
console.log("onopen()");
/// do some very important stuff after connection has been established
}
}
你放心,这个例子没问题。 Javascript 事件循环将在承担任何其他任务之前完成当前任务。这意味着 1) WebSocket 无法在 onopen
事件之前打开连接(异步操作),2) onopen
事件处理程序将在以下周期中被调用。
另一方面,设置超时会使事情复杂化,因为事件将在当前任务之后按某种顺序调用。这意味着 WebSocket 有机会在设置处理程序之前打开连接。
你应该读一读 javascript 的事件循环:https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop
如果您查看有关 Run-to-completion
的部分,您会得到以下有用的解释:
Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it may be stopped at any point by the runtime system to run some other code in another thread.
因此在您的示例中,对 ws.onopen
的赋值必须在 websocket 执行本质上异步的任何操作之前完成。通过将您的分配放在 setTimeout
内,您将它移出当前 运行 上下文,因此它可能不会在 websocket 需要它之前执行。