Ticket #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: | ||
| Blocking: | Blocked by: |
Description (last modified by rwaldron) (diff)
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
comment:1 follow-up: ↓ 2 Changed 3 years ago by rwaldron
- Status changed from new to closed
- Resolution set to invalid
comment:2 in reply to: ↑ 1 Changed 3 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 follow-up: ↓ 5 Changed 3 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 3 years ago by rwaldron
- Description modified (diff)
synchronous xhr is almost always a bad idea
comment:5 in reply to: ↑ 3 Changed 3 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 3 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 6 weeks 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 6 weeks 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 6 weeks 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!
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

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.