Bug Tracker

Opened 9 years ago

Closed 9 years ago

Last modified 6 years ago

#7464 closed bug (invalid)

Synchronous AJAX calls prevent DOM updates made BEFORE call

Reported by: swiftone@… Owned by:
Priority: undecided Milestone: 1.5
Component: unfiled Version: 1.4.3
Keywords: Cc:
Blocked by: Blocking:

Description (last modified by Rick Waldron)

Seen in Chrome 7, IE 8

Works as expected in FF 3.6.6

With a synchronous AJAX call, DOM updates made shortly before the AJAX call do not occur until the call is complete.

With a series of synchronous calls, updates in any of them will not occur until series is complete.

Demo: [

Previously encountered by someone else: [

Change History (13)

comment:1 Changed 9 years ago by Rick Waldron

Resolution: invalid
Status: newclosed

You answered this yourself:

async: false, If true this runs as expected, if false the DOM is not updated until complete

That is the nature of asynchronous and synchronous XHR calls. In fact, setting async:false will BLOCK execution of code until it returns a response.

This is not a jquery bug.

Last edited 9 years ago by Rick Waldron (previous) (diff)

comment:2 in reply to:  1 Changed 9 years ago by swiftone@…

Replying to rwaldron:

That is the nature of asynchronous and synchronous XHR calls. In fact, setting async:false will BLOCK execution of code until it returns a response.

Please READ the ticket/view the demo. It shouldn't block execution of code made BEFORE the $.ajax() call.

If I show a message (say..."Loading") BEFORE I make the AJAX call, I'd expect it to display.

Likewise, in a sequence of AJAX calls, I'd expect changes made in those calls to be applied before the blocking began for the next call.

comment:3 Changed 9 years ago by dmethvin

If I show a message (say..."Loading") BEFORE I make the AJAX call, I'd expect it to display.

The code before the call is running, but that doesn't mean you will see the result immediately. If the call is truly and completely synchronous, the window update might not happen until after the $.ajax call completes. It wouldn't be any different than:

$("#status").text("Working...");
for ( var i=0; i < 100000; i++ ) { /* calculate stuff */ }
$("#status").text("Done.");

comment:4 Changed 9 years ago by Rick Waldron

Description: modified (diff)

synchronous xhr is almost always a bad idea

comment:5 in reply to:  3 Changed 9 years ago by swiftone@…

Replying to dmethvin:

the result immediately. If the call is truly and completely synchronous, >the window update might not happen until after the $.ajax call completes.

Perhaps this is where I'm lost. I'd not expect a window update to be a separate process that doesn't happen serially when my code changes the DOM.

If that's the case, okay then (but that opens new areas like...why can't we send hints to this process to say "hold off on updating" and "okay, now you can" or the like....)

comment:6 Changed 9 years ago by ajpiano

The amount of time that takes place in between the time you invoke $.ajax() and the time the request is completely prepared and dispatched is infinitessimal, nearly impossible to measure over a single iteration. If the UI thread of the browser hasn't finished drawing whatever updates it has to make to the page by the time that the sync request is dispatched, the browser will LOCK immediately.

Given the general unadvisability of synchronous XMLHttpRequests, jQuery is not going to put in any sort of convoluted "fix" to allow the browser a few additional nanoseconds in which to complete its rendering business before making the request. That is why we do not consider this to be a bug.

One hack people tend to use to give the browser some "breathing room" is to wrap code that needs to wait for UI updates in a short timeout... for instance:

setTimeout(function() {
$.ajax({"iHateMyUsers.php",async:false});
},13)

comment:7 Changed 7 years ago by anonymous

I have been banging up against this problem all morning and ajpiano's response is only partially helpful. The first paragraph does a good job of explaining the problem, but the second and third paragraphs basically say, "If you have this problem, you're an idiot." A more helpful answer would respect that there is a legitimate need to be able to display a "working..." message before a long AJAX call and offer a solution that doesn't presume "iHateMyUsers".

comment:8 Changed 7 years ago by dmethvin

the second and third paragraphs basically say, "If you have this problem, you're an idiot."

Sorry, the correct interpretation should be "If you have this problem, you do not understand the single-threaded browser environment." It's okay to not understand something, but please don't blame jQuery for it. You can fix this problem with a setTimeout but jQuery cannot fix it for you.

comment:9 Changed 7 years ago by swiftone@…

Original bug poster here! I'll say at the time I was quite annoyed at the dismissive response and it was only after the back-and-forth that I figured out that the UI refresh is itself asynchronous from the rest of the execution - something that I'd never seen documented (still haven't, though I rarely delve into specs). Had that distinction been made clear at the start it would have saved a lot of gnashing of teeth. (however, bonus points to the jQuery team for quick responses and not ignoring the bug)

That said, the discouragement about avoiding sync ajax requests is quite technically correct (all that was missing was the "why"). Synchronous AJAX requests should be avoided not just because they block all other ajax requests, but because they block UI refresh and who-knows-what other async pieces of the browser JS environment, even in-between your synchronous calls.

Since this bug Promises have been added which makes it much easier to "queue" a series of calls or have a swarm of calls that you react to only when they are all complete. Given that, I'd avoid the "setTimeout" option listed here as obsolete and shoot for promises instead. Hope that helps!

comment:10 Changed 6 years ago by ajusco@…

OK, understood that the synch ajax blocks the DOM update, etc. But how come this does not happen in FF?

In this case does the DOM update keep working while the ajax thread is run separately? So the queued actions are not blocked (which seems to be the right way), and thus is this rather a Chrome+IE bug?

comment:11 Changed 6 years ago by anonymous

Synchronous call is preferable in some cases. If updating the DOM does not happen as my code progresses, it is definitely a bug. FF is correct. Chrome is wrong. And I think that is what JQuery should say. It is NOT the correct behavior.

comment:12 Changed 6 years ago by dmethvin

The important thing to the people posting here is that this is a condition that jQuery cannot do anything about. If you think Chrome or IE should do it differently you would need to talk to them. So please stop opining here.

comment:13 in reply to:  3 Changed 6 years ago by anonymous

Replying to dmethvin:

If I show a message (say..."Loading") BEFORE I make the AJAX call, I'd expect it to display.

The code before the call is running, but that doesn't mean you will see the result immediately. If the call is truly and completely synchronous, the window update might not happen until after the $.ajax call completes. It wouldn't be any different than:

$("#status").text("Working...");
for ( var i=0; i < 100000; i++ ) { /* calculate stuff */ }
$("#status").text("Done.");

Well-explained. This was annoying me for awhile. There is no guarantee the window will update everything you have done prior before initiating the synchronous action and blocking everything. Use asynchronous with other means (like disabling the run button) to prevent the user doing actions you don't want prior to the call completing. It's much better.

Note: See TracTickets for help on using tickets.