#7366 closed enhancement (invalid)
Asynchronously loading scripts need special care with jQuery.fn.ready
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | undecided | Milestone: | |
Component: | unfiled | Version: | 1.4.3 |
Keywords: | needsreview | Cc: | |
Blocked by: | Blocking: |
Description
Current implementation of jQuery.fn.ready is like this.
ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // If the DOM is already ready if ( jQuery.isReady ) { // Execute the function immediately fn.call( document, jQuery ); // Otherwise, remember the function for later } else if ( readyList ) { // Add the function to the wait list readyList.push( fn ); }
When a script author writes a script that loads via <scirpt> tag, they can do something like this.
$(function() { foo(); }); var foo = function(){ };
Since $() executes the function asynchronously, the "foo" function will be defined. So there is no problem. But if they start to try <script async> or a custom script loader such as LABjs, and if $() becomes synchronous, this script won't work any more because "foo" will be undefined.
In the case of <script async>, you can't be sure if the script comes before or after DOMContentLoaded. It may be working in the local server where script loads in a moment, but not working somewhere where it takes 5 seconds to load the script.
I think jQuery.fn.ready should execute the function asynchronously even if jQuery.isReady is true, so that scripts are more portable.
Change History (4)
comment:1 Changed 13 years ago by
Keywords: | needsreview added |
---|---|
Milestone: | 1.5 |
comment:2 Changed 13 years ago by
I agree that it's a badly written code, but the I can easily imagine people do it. It's not easy to debug too (in the case of <script async>).
Use function declarations instead of function literals.
You can't always replace a function declaration with a function literal.
$(function() { foo.bar(); }); var foo = { bar : function() {} };
Use function literals, but define them before calling $.fn.ready.
Yep, if all scripts were written this way, I wouldn't worry. In reality it's not the case.
Even if the calls are deferred, you are not guaranteed that a deferred call is going to occur after all asynchronous scripts load
The case I'm talking about does not require ALL scripts to load. Just to wait for parsing of the very script.
comment:4 Changed 12 years ago by
Resolution: | → invalid |
---|---|
Status: | new → closed |
If we implemented this we'd be making a significant breaking change, because this has been in the .ready()
documentation for some time:
If .ready() is called after the DOM has been initialized, the new handler passed in will be executed immediately.
So I'm going to close this ticket.
Basically, the complaint here is that because
$.fn.ready
doesn’t unconditionally defer the execution of the function that is passed to it, badly written code with race conditions that incorrectly expect the call will always occur only after the caller has returned will sometimes experience…race conditions.I’m loathe to call these workarounds since they really are not workarounds but proper coding practice, but the “workarounds” here are:
$.fn.ready
.Even if the calls are deferred, you are not guaranteed that a deferred call is going to occur after all asynchronous scripts load, so I am not sure this suggestion will actually solve anything related to the original complaint regarding asynchronously loaded scripts.