1

我有如下代码:

var ws = new WebSocket("ws://localhost");
ws.onopen = function() {
    // Long running loop
    for (var i = 0; i < 1000000; i++) {
        ws.send(i);
        console.log(i);
    }
};

服务器只在循环完成后接收消息(或者我相信客户端只开始发送消息)。为什么会这样?

4

2 回答 2

2

页面的一些执行领域是:

  • JavaScript
  • DOM 渲染
  • 网络

我已经有一段时间没有对此进行测试了,但我假设情况仍然如此,如果您执行一个函数(或在一个范围内运行代码),那么如果您调用更新 DOM 或发出网络请求在当前范围存在之前不会发生这种情况。

例如

function doSomething() {
  document.body.innerHTML += 'hello';
  var ws = new WebSocket('ws://my-websocket-endpoint.com');
  ws.onopen = function() { alert( 'awesome!' ); };
}

doSomething();

在上面的代码中会发生以下情况:

  • doSomething执行并运行内部代码。
  • doSomething返回和范围变化
  • 'hello' 然后出现在 DOM 中,因为浏览器让 UI 线程有机会运行任何挂起的更新
  • 已建立 WebSocket 连接
  • alert距离火灾可能还有一段时间。

具体看WebSocket例子。如果您考虑我们可以在创建WebSocket实例后添加事件处理程序的事实,这意味着一旦我们调用构造函数就不会发生连接。仅当当前执行范围完成时才尝试连接。我不能 100% 确认这一点,但WebSocket.send在执行范围完成之前,该函数实际上发送任何数据的可能性也很小,例如

var ws = new WebSocket('ws://my-websocket-endpoint.com');

function sendStuff() {
  for( var i = 0; i < 10000; ++i ) {
    ws.send( i );
  }
}

// Assume we are connected
sendStuff();

在上面的代码中,我期望:

  • sendStuff被调用,运行循环并退出
  • 然后浏览器处理任何其他未决的事情,包括网络活动。这包括实际发送数据
于 2012-10-27T11:37:35.433 回答
1

它没有回答您的问题,但值得注意的是您的代码看起来不正确。

您的new WebSocket调用启动与服务器的异步握手。完成后,onopen您在 websocket 上注册的任何回调都将运行。只有此时您才能调用ws.send并期望服务器接收您的消息。

然后你可以修改你的例子

var ws = new WebSocket("ws://localhost");
ws.onopen = function() {
    for (var i = 0; i < 1000000; i++) {
        ws.send(i);
        console.log(i);
    }
};
于 2012-10-27T17:49:39.317 回答