11

Suppose I have a event handler which makes two AJAX calls to the server:

$("#foo").click(function(){ 
    $.get("bar", function(){ alert("Hello"); });
    $.get("baz", function(){ alert("World"); });
});

I realize that the order in which the callbacks are invoked is nondeterministic, since it depends on how long each request takes, etc.

But here's my question: is it guaranteed that I'll reach the end of my event handler before either of the callback functions are invoked? I've read that all Javascript for a page executes in a single thread, so I think that implies that my click event handler is guaranteed to complete before any of the callbacks can be invoked.

Is this correct? Or is it possible that the first request might be complete AND the first callback executed before we even get to the end of our event handler?

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256

4 Answers4

11

Yes, this is guaranteed and you are right - there is just a single thread (ignoring s for the moment). When a piece of JavaScript code executes (occupies the execution thread) and an AJAX callback arrives (or any other GUI event, timeout, etc.) it is queued and waits until the execution thread is free (current piece of code finishes).

JavaScript engine will never interrupt running code to handle incoming event - events will always gently wait in a queue. This is the reason why the GUI appears to be freezing when CPU-intensive code is executing - no events are handled. Also this is why synchronous AJAX requests are bad.

See also

Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
4

Yes, JavaScript is single threaded, so your execution will never get preempted.

Asynchronous callbacks and events work the same way; your handler for mousedown is guaranteed to finish before your handler for a mouseup, even if your mousedown handler takes 2 seconds and you let the mouse go immediately.

The same goes for an AJAX callback, it gets put into the same (kind of) queue as events waiting to be processed

Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
1

An interesting twist to this would be instead of $.get(), lets say we were using promises that we get from somewhere else (i.e. the actual async call was made elsewhere) (-Why would we have such a situation? Well maybe we have a memoized query function.)

Now if one were using jQuery promises, the callbacks would be invoked synchronously if already resolved. Is that ever an issue? Well depends on your requirement. If it does then you could wrap the callback code in a setTimeout(cb, 0).

On the other hand, what if you wanted the callbacks to be preempted? See my examples here

Ustaman Sangat
  • 1,505
  • 1
  • 14
  • 26
0

I realize that the order in which the callbacks are invoked is nondeterministic, since it depends on how long each request takes, etc.

In the way you have written it yes.. but there are ways to organize and control this.. namely deffereds and promises.

Here is a good overview: http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/

Proper use of them will ensure that you won't run into whatever problem you seem to be trying to avoid.

** As @Juan has pointed out, this isn't the black and white answer for the question you asked. I'm just trying to point you in different directions or ways to look at the same problem so you can define your expected behavior more explicitly.

Patrick Lee Scott
  • 8,217
  • 3
  • 36
  • 42
  • 1
    OP is not asking about async tasks coming back out of order – Ruan Mendes Apr 03 '12 at 19:18
  • No he's not, but I'm saying if he controls all of his async callbacks than he probably won't encounter the problem he's trying to avoid in the first place. Which seems to be about making sure a handler finishes before other handlers. – Patrick Lee Scott Apr 03 '12 at 19:20
  • "Is this correct? Or is it possible that the first request might be complete AND the first callback executed before we even get to the end of our event handler?" If it's programmed in a way that makes it explicit, than he wouldn't have this question, would he? – Patrick Lee Scott Apr 03 '12 at 19:22
  • 1
    I might be over-analyzing his question and providing solutions to problems that I implied from his question where he may have just been curious, though. – Patrick Lee Scott Apr 03 '12 at 19:23
  • 2
    The problem is: The click handler fires an AJAX request, is it possible that the success callback is called before the click handler finishes? It's not about tracking/wrangling async tasks. What you said makes sense, but since it's not really answering the question, it is more likely to confuse the OP – Ruan Mendes Apr 03 '12 at 19:24
  • 1
    Instead of making sure you write the code in the correct order so handlers are sent to the event queue at the correct time so everything can happen without breaking.. Just trying to point him in the right direction to make things easier to handle in the first place. :) I do see your point though – Patrick Lee Scott Apr 03 '12 at 19:24
  • @Patrick: Thanks for the link, Juan is correct that it's not entirely what I was asking about, but I was not confused and appreciate it, since I was not previously familiar with jQuery promises. – Eli Courtwright Apr 03 '12 at 19:38