Opened 11 years ago
Closed 10 years ago
#12044 closed feature (wontfix)
ready callback should always be called asynchronously
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | low | Milestone: | 1.9 |
Component: | deferred | Version: | 1.7.2 |
Keywords: | Cc: | ||
Blocked by: | #10467 | Blocking: |
Description
The documentation of ready
says:
If
.ready()
is called after the DOM has been initialized, the new handler passed in will be executed immediately.
...and by "immediately" it means "synchronously."
Which is a problem: The handler should always be called asynchronously, even if the DOM is ready. This prevents ready
from having chaotic behavior. For instance, it's impossible to look at this code and determine the order in which "B" and "C" are logged:
console.log("A"); jQuery(function($) { console.log(B"); }); console.log("C");
In the normal case (DOM not yet ready when ready
is called), we'll get
A C B
...but if the DOM is already ready, we'll get
A B C
This allows bugs to slip in, where there is an undetected dependency on the order of B and C and a script is only tested in one situation or the other.
Somewhat gratuitous example showing the three situations in which ready
might be called (1. DOM not ready; 2. During another ready
handler; 3. DOM ready), and how they behave: http://jsbin.com/ezowij The output is:
Outer `ready`: ACB Inner `ready`: ACB Delayed `ready`: ABC
Note the third is different. My belief is that if a callback may be asynchronous, it should always be asynchronous, and so I'd rather see consistency.
Change History (11)
comment:1 Changed 11 years ago by
comment:2 Changed 11 years ago by
Component: | unfiled → deferred |
---|---|
Milestone: | None → 1.9 |
Priority: | undecided → low |
Status: | new → open |
comment:3 Changed 10 years ago by
Type: | enhancement → feature |
---|
Bulk change from enhancement to feature.
comment:4 Changed 10 years ago by
Blocked by: | 10467 added |
---|
comment:5 follow-up: 6 Changed 10 years ago by
Leaving this open since it can be solved with setTimeout. Is it worth adding that though?
comment:6 Changed 10 years ago by
comment:7 follow-up: 8 Changed 10 years ago by
The downside is that it probably adds at least 16ms of delay to document ready for everyone, since APIs like setImmediate()
aren't available.
comment:8 Changed 10 years ago by
Replying to dmethvin:
The downside is that it probably adds at least 16ms of delay to document ready for everyone, since APIs like
setImmediate()
aren't available.
If you're optimizing to that level, you don't use ready
anyway, although in my tests setTimeout
only routinely adds 15ms in IE; on Chrome I get 7ms on average, Opera about 7.5ms, and Firefox less than 4ms.
I would also advocate only using setTimeout
when the DOM is already ready, but a quick look at the latest suggests ready
has been promise
-ified which might make that difficult.
comment:9 Changed 10 years ago by
I've started looking at this today and will take ownership of it if no one else has made any progress.
comment:10 Changed 10 years ago by
It's a -1 for me. The consistency argument seems rather specious to me.
comment:11 Changed 10 years ago by
Resolution: | → wontfix |
---|---|
Status: | open → closed |
This really comes down to the same problem we've argued ad nauseum with promises and their sync/async resolution. For better or worse, we have quite a bit of code that depends on the current behavior and we've documented that the callback is called "immediately" when the DOM is ready.
The good news is that someone who needs the async resolution is free to guarantee that with a setTimeout()
inside their own code. If were were to "fix" this, it wouldn't be possible to get the synchronous behavior back.
If/when #10467 is resolved, this will automatically happen :-)