4

Suppose a javascript task makes an async call. e.g. xhr.send(stuff)

  1. Does the (async) send begin in another thread immediately? or
  2. Does the send not begin until the current task is complete?

I am pretty sure it is (2) the latter but is this behavior covered by a spec or is it just the typical implementation. In a similar vein... Is the creation of a listener considered a synchronous call? Is there a specification covering this?

phreed
  • 1,759
  • 1
  • 15
  • 30
  • 2
    AFAIK it's actually #1, but I can't quote chapter and verse. – Alnitak Dec 13 '16 at 17:48
  • Perhaps this can help you a bit: http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background/7575649#7575649 . About point 1.. I'm not sure, since javascript is running on a browser and the browser should be single-thread, I don't see how it should spawn another thread, it should just be event-based. – briosheje Dec 13 '16 at 17:53
  • 2
    @briosheje there's nothing to say that browsers can't spawn threads for internal purposes. It would be simpler than using event driven I/O which might be tricky to mesh nicely with the user-facing event dispatch loop. [or in other words, if you start up a long-lived task in user facing code, how would you ensure it doesn't block ongoing AJAX requests it they shared the same event queue? ] – Alnitak Dec 13 '16 at 17:53
  • 1
    The reason I think that it is (2) is because if I call both xhr.send() followed by xhr.addEventListener() the sources I have found assure me that there is no chance that the listener will miss the event for which it is listening. In the case of (1) there is a chance (although minuscule) that the async task could complete before the current task. – phreed Dec 13 '16 at 17:57
  • 3
    @phreed that's different - the _async result_ of the XHR send will be added to the event queue, and the event queue won't be looked at until _all currently running code blocks_ have completed. You specifically asked about when the send _starts_, though. Tasks aren't "lines of code" or individual function calls - it's any and _all_ code currently executing as the result of the previously triggered event. – Alnitak Dec 13 '16 at 17:58
  • @Alnitak: that's exactly what I've ever wondered, though I've always read everywhere that javascript is single-thread. So is it technically true to say that a browser can spawn threads for internal purposes? I've always wondered such for WebWorkers aswell. – briosheje Dec 13 '16 at 17:59
  • 1
    @briosheje as far as the _user_ is concerned, Javascript executes within a single thread (notwithstanding WebWorkers). The implementation is free to use threads however it wants, though. – Alnitak Dec 13 '16 at 18:01
  • 1
    As Alnitak has said, from the user side, JS is single threaded and [operates on an event queue](http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background). However, browsers are allowed to actually initialize and run asynchronous code however they want. [Firefox appears to use threads under the hood](https://github.com/AllenDou/firefox/blob/eacebdd2dcbce6bf04fad19efeb1ded9931b46a3/content/base/src/nsXMLHttpRequest.cpp#L2688). – Mike Cluck Dec 13 '16 at 18:02
  • @Alnitak: Oh, thanks. Didn't know that. – briosheje Dec 13 '16 at 18:06
  • @Alnitak Isn't it the listener that provides the instruction to place the async result into the event queue? If the async result arrives before the listener is created what gets put in the event queue? The async result itself is not a task. – phreed Dec 13 '16 at 18:06
  • I think I see now. The async task results in a task being added to the event queue as @Alnitak said. The task looks for listeners for the associated event. If there are no listeners then the result is silently dropped. http://stackoverflow.com/questions/7575589/how-does-javascript-handle-ajax-responses-in-the-background?noredirect=1&lq=1 gives quite a bit of detail. – phreed Dec 13 '16 at 18:14

1 Answers1

1

This question was mostly answered by @Alnitak, https://stackoverflow.com/a/17439761/345427, https://youtu.be/8aGhZQkoFbQ and definitively by https://www.w3.org/TR/html51/webappapis.html#event-loops

The implementations can vary somewhat but the semantics seem to be as outlined in this summary.

  1. The async call (typically) causes execution to begin in a separate thread immediately. [e.g. xhr.send()]
  2. The event listener creation happens synchronously. [e.g. xhr.addEventListener()]
  3. When the async task completes a new task, representing the async result is added to the task-queue
  4. The event-loop reads the task-queue and evaluates the next task
  5. The async result has an associated callback which checks the listeners registered for the result.

Here is an example of how an async task works. https://chromium.googlesource.com/chromium/blink.git/+/99b8c9800ac123eddc3e199088d22569c5294b22/Source/core/xml/XMLHttpRequest.cpp

As you can see from the code there are several places where tasks are added to the task queue, dispatchEvent() gets called.

Community
  • 1
  • 1
phreed
  • 1,759
  • 1
  • 15
  • 30