我怎样才能保证调用websocket onopen

时间:2018-03-10 14:12:53

标签: javascript websocket

我在WebSocket中使用javascriptWebSocket需要url作为构造函数参数并立即尝试连接。我只能在构造它之后设置onopen方法。

因此,如果WebSocket在设置onopen之前已经建立了连接,那么我会错过onopen事件!

我该如何避免这种情况?

模拟它:

A)

1)在Chrome中,打开websocket。 2)按F12打开开发人员工具。 3)打开控制台 4)立即复制并粘贴所有这些代码!进入!

uri = "ws://echo.websocket.org?encoding=text";
websocket = new WebSocket(uri);
websocket.onopen = function(evt) { console.log('EHE')};

B)

重复1-2-3

4)复制并粘贴这些代码并运行

uri = "ws://echo.websocket.org?encoding=text";
websocket = new WebSocket(uri);

5)等一下

6)运行此代码:

websocket.onopen = function(evt) { console.log('EHE')};

结果:

在A)中打开onopen。在B)我们错过了它!

1 个答案:

答案 0 :(得分:4)

由于Javascript的单线程事件驱动特性,您所描述的内容不会在实际代码中发生。 "打开"在您当前的Javascript部分完成之后,才能触发事件。因此,您始终可以在事件发生之前设置onopen事件处理程序。

在调试器或控制台中插入人为暂停是一种人为的情况,在实际代码中不会发生。

实际代码中会发生什么:

  1. 您致电new WebSocket(uri)
  2. webSocket intrastructure启动webSocket连接(异步操作)
  3. webSocket构造函数在该连接完成之前立即返回。
  4. 运行其余代码(包括分配.onopen属性并设置事件处理程序。
  5. Javascript解释器已完成运行您的代码并返回事件循环。
  6. 如果到目前为止,webSocket已连接,那么事件队列中将出现open事件,Javascript将触发该事件,导致您的.onopen处理程序被调用。
  7. 如果open事件尚未完成,Javascript将等待下一个事件插入到事件队列中并运行它,一遍又一遍地重复该过程。最终,其中一项活动将是您的open活动。
  8. 关键是通过异步事件调用.onopen。因此,它必须通过Javascript事件队列。并且,直到您当前的Javascript部分完成并返回到解释器之后,才能运行事件队列中的事件。那是"事件驱动的" Javascript的本质是有效的。因此,由于该体系结构,只要您在调用构造函数的Javascript的同一部分中安装onopen处理程序,就不会错过.onopen事件。

    如果它给你带来任何舒适感,那么node.js中有许多API都依赖于同样的概念。例如,当您使用fs.createReadStream(filename)创建文件流时,您必须创建流,然后添加事件处理程序(其中一个事件处理程序用于open事件)。同样的逻辑适用于那里。由于Javascript的事件驱动性质,没有竞争条件。在其余的Javascript运行之前,无法触发open事件或error事件,因此您始终有机会安装事件处理程序,然后才能调用它们。

    如果可以同步检测到错误(如错误的文件名或错误的uri)并且可能立即触发error事件,则使用setImmediate(function() { /* send error event here*/ })之类的代码进行编码以确保错误事件不是在您的代码有机会安装事件处理程序之前触发。