Skip to main content

Bug Tracker

Side navigation

#7464 closed bug (invalid)

Opened November 10, 2010 07:45PM UTC

Closed November 10, 2010 07:55PM UTC

Last modified March 25, 2014 08:46PM UTC

Synchronous AJAX calls prevent DOM updates made BEFORE call

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

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:

[

Attachments (0)
Change History (13)

Changed November 10, 2010 07:55PM UTC by rwaldron comment:1

_comment0: You answered this yourself: \ \ async: false, \ //If true this runs as expected, if false the DOM is not updated until complete \ \ That is in fact 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.1289419137590211
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.

Changed November 10, 2010 08:05PM UTC by swiftone@swiftone.org comment:2

Replying to [comment:1 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.

Changed November 11, 2010 04:08AM UTC by dmethvin comment:3

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.");

Changed November 11, 2010 04:50AM UTC by rwaldron comment:4

description: 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: \ [http://jsfiddle.net/Gr4WP/11/] \ \ Previously encountered by someone else: \ [http://forum.jquery.com/topic/execpt-for-ff-all-browsers-miss-dom-update-before-ajax-call-any-ideas]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: \ [

synchronous xhr is almost always a bad idea

Changed November 11, 2010 05:30AM UTC by swiftone@swiftone.org comment:5

Replying to [comment:3 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....)

Changed November 11, 2010 06:42AM UTC by ajpiano comment:6

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)

Changed April 08, 2013 07:03PM UTC by anonymous comment:7

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".

Changed April 08, 2013 07:15PM UTC by dmethvin comment:8

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.

Changed April 09, 2013 08:07PM UTC by swiftone@swiftone.org comment:9

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!

Changed July 03, 2013 05:12AM UTC by ajusco@gmail.com comment:10

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?

Changed August 19, 2013 06:12PM UTC by anonymous comment:11

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.

Changed August 19, 2013 06:33PM UTC by dmethvin comment:12

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.

Changed March 25, 2014 08:46PM UTC by anonymous comment:13

Replying to [comment:3 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.