简体   繁体   中英

The mechanics of the JavaScript WebSockets API

I've been trying to understand some code used to open a websocket:

var ws = new WebSocket('ws://my.domain.com');
ws.onopen = function(event) {
    ...
}

My question is how does the handshaking get started? If it is started in the WebSocket constructor, then how does onopen get called if it isn't set by then? If the WebSocket constructor creates a thread that does the handshaking, then does onopen have to be defined quickly enough before the handshaking is over? If so, that sounds a little dangerous because if the JS virtual machine is slowed the handshaking could be finished before onopen is defined, which means that the event is not handled. Or does setting the onopen function trigger the handshaking?

Could someone explain to me the mechanics of the API please?

It does not look for onopen function until end of execution of current (synchronous) code. That is because the connection (and thus calling onopen callback) is asynchronous. Consider:

let x = false;
setTimeout(function () {
    x = true
}, 1000);
while(!x){
    console.log('waiting!');
}

The while loop there will never end but you would probably suspect it'd end after one second.

If you delay the initialisation of onopen function by executing time-consuming (but synchronous) code then it is not dangerous. On the other if you setTimeout initialisation of onopen then there's no guarantee whether it's defined or not at the time the WebSockets connection is ready as you can't be sure which callback will be executed first.

If you were doing the same thing in C++ you'd use threads for that. In JavaScript callbacks mechanism is not thread-based; it just behaves thread-like (see the endless while loop above).

Single thread executes one code-unit at a time and other code units are queued until the current code unit is finished executing

source: http://www.slideshare.net/clutchski/writing-asynchronous-javascript-101

It's important to understand that even if you setTimeout something for 1s it might not execute after one second - If the thread is busy it might never get executed.

Thus if you initiate WebSocket connection and run a loop similar to the one above but waiting for the connection to be ready it might never end.

This behaviour might look strange for programmers not familiar with JS. Therefore for readability I define callbacks at the same time or immediately after the functions which need them whenever it's possible.

If you want to explicitly use threads and concurrent execution, read more about Web Workers

Reference:

You don't need any setTimeout function. I'm using a library for this and my code looks something like this:

var pushstream = new PushStream({
  host: window.location.hostname,
  port: window.location.port,
  modes: "websocket"
});
pushstream.onmessage = _manageEvent;

function _manageEvent(eventMessage) {
  console.log(eventMessage);
}

This gave me a hell of an insight on websockets and how to implement a client in Javascript: https://github.com/wandenberg/nginx-push-stream-module/blob/master/misc/js/pushstream.js

And also the server: https://github.com/wandenberg/nginx-push-stream-module/

It's very well documented I hope it helps :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM