简体   繁体   中英

Why does WebSocket event listeners work if they are registered after events are fired?

According to MDN docs , the WebSocket event listeners are registered after the connection is created, and the process is sequential:

// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// Connection opened
socket.addEventListener('open', function (event) {
    console.log('ws connected');
});

// Listen for messages
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

How does this work if events start firing before the listeners were registered? Say, the connection opened before the open listener is registered, or messaged came in before the message listener is registered.

I would expect the events to be lost since the event listeners are not registered yet, according to the MDN doc on Concurrency model and Event Loop :

In web browsers, messages are added anytime an event occurs and there is an event listener attached to it. If there is no listener, the event is lost. So a click on an element with a click event handler will add a message--likewise with any other event.

I tried to add some expensive ops in between, but it seems that the open and message event listeners only trigger after all the event listeners are properly registered. Are the WebSocket features async in nature?

// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');

// expensive ops
for (var i = 5000; i >= 0; i--) {
  console.log('1');
}

// Connection opened
socket.addEventListener('open', function (event) {
    console.log('ws connected');
});

// expensive ops
for (var i = 5000; i >= 0; i--) {
  console.log('2');
}

// Listen for messages
socket.addEventListener('message', function (event) {
    console.log('Message from server ', event.data);
});

// prints "1"s, then "2"s, then "ws connected", then "Message from server"

You can't add events before an object is created so they have to be afterwards. This all works because JavaScript is single-threaded and events are handled in the same thread so nothing can happen while code is running. You can delay the execution for a year and only after your code finishes will the runtime start handling any events that have arrived while it was running. The socket might not even start connecting before your code finishes.

Therefore it's guaranteed that no events will go amiss.

Mozilla Developer Network has a good explanation of the event loop , the “Run to Completion” talks about the nature of JS runtime.

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