开发者

Is it possible to "miss" an async event in JS if you subscribe for it after you've asked for its triggering?

开发者 https://www.devze.com 2023-03-26 17:11 出处:网络
Here i开发者_StackOverflow中文版s a simple snipped to do an Ajax request var req = new XMLHttpRequest();

Here i开发者_StackOverflow中文版s a simple snipped to do an Ajax request

var req = new XMLHttpRequest();
req.open('GET', 'http://www.mozilla.org/', true);
req.send(null); // First - send the request
// Then bind for the "result"
req.onreadystatechange = function (e) {
    if (req.readyState == 4 && req.status == 200) {
        // ...
    }
};

What I am doing here:

  1. Sending the Ajax request.
  2. And then binding for the result callback.

If you think of this code as multithreaded - it is obvious that you can bind to onreadystatechage after the request has finished (due to scheduling) and it will never be called.

But in reactor-based code, this will work as expected all times since the reactor will not run until after all my code has finished running for that iteration.

Which is the case in browsers? Has this been documented somewhere?

Ignore that fact that an Ajax request is a slow thing and this might never happen in practice. I'm just giving it as an async example (think websocket if ajax is too slow for you).


JavaScript is not multithreaded in that sense. After you have said.send(null), you will finish executing your current block of code, which includes that onreadystatechange, and only then will events be fired. Your code will not be interrupted between those two sentences for an event firing - the event will be added to an event queue (buffered, if you will), and when there is time, the event will fire, calling all the handlers associated to it. It should call handlers that have been added between the creation of the XMLHttpRequest object and the firing of the event.

At least, this is my interpretation of the issue. For more information, visit Timing and synchronization in Javascript, at dev.opera.


In theory no, firing of event handlers are supposed to happen on the event queue so would have to happen in a time slice after the current time slice completes, which would mean that the req.onreadystatechange = ... happens before any events are handled. See javascript - event driven and concurrency issues? to understand JavaScript's concurrency model (at least in the browser).

In practice, Firefox used to have (may still have) a bug where the onreadystatechange event in particular was fired concurrently with the event queue of the frame whose XMLHttpRequest object was used to send the request. I got into the habit of having my onreadystatechange handlers do a setTimeout(0, ...) to make sure I didn't get nasty interleavings on Firefox.

It's also possible if you use an XMLHttpRequest object cross-frame as in new otherWindow.XMLHttpRequest(...) because then the response could be handled on the other frame's event queue before the current time-slice (in this frame's event queue) finishes.


Is it possible to “miss” an async event in JS if you subscribe for it after you've asked for its triggering?

No, this is not possible - if you bind the handler before the event occurs.

The event occurs anyway. When it does, all handlers that are registered at this point in time will be called.


Theoretically it is possible.

To avoid it put req.onreadystatechange = ... before req.send(null);.

0

精彩评论

暂无评论...
验证码 换一张
取 消