SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Enthusiast
    Join Date
    Sep 2008
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Loading scripts in parallel causes bug in WebKit browsers

    Hi,

    I have a function called 'loadScript' which is used to load JavaScript files in parallel (for the purpose of not blocking the browser from downloading other components at the same time).

    See the following link for more information on the subject:
    http://www.stevesouders.com/blog/200...hout-blocking/

    This function works fine for IE and Firefox and up until today has always worked for Chrome/Safari. But today I noticed an issue for WebKit rendering engines, which is that sometimes the callback method I pass to the loadScript doesn't always fire, only sometimes when I force refresh the page.

    The code for the loadScript function is as follows...

    Code JavaScript:
    var loadScript = function(url, callback)
    {
    	var script = document.createElement("script");
    	script.type = "text/javascript";
     
    	if (script.readyState) { // Internet Explorer
    		script.onreadystatechange = function()
    		{
    			if (script.readyState == "loaded" || script.readyState == "complete") {
    				/*
    				 * Oddly the final readyState isn稚 always "complete". 
    				 * Sometimes, readyState stops at "loaded" without going on to "complete" 
    				 * and sometimes it skips over "loaded" altogether. 
    				 * 
    				 * The best approach is to check for both readyState values 
    				 * and remove the event handler in both cases to ensure you don稚 handle the loading twice:
    				 */
    				script.onreadystatechange = null;
    				callback();
    			}
    		};
    	} else {
    		script.onload = function()
    		{
    			callback();
    		};
    	}
     
    	script.src = url;
    	document.getElementsByTagName("body")[0].appendChild(script);
    };

    ...and I call the function in my HTML page as follows...

    Code JavaScript:
    <script src="Assets/Scripts/loadScript.js"></script>
    <script>
    	loadScript("Assets/Scripts/Library.js", function() {
    		STORM.init();
    	});
    </script>

    Any help would be really appreciated as this is confusing the hell out of me

    Kind regards,
    M.

  2. #2
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Are any javascript errors produced?

  3. #3
    SitePoint Enthusiast
    Join Date
    Sep 2008
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    That's the really annoying thing, there are no errors!

    Sometimes it will run, sometimes it wont.

    So frustrating having to work out what's going on with something if it doesn't have the decency to at least throw you an error somewhere along the line.

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    looks like others have had the same problem
    safari script onload

  5. #5
    Function Curry'er JimmyP's Avatar
    Join Date
    Aug 2007
    Location
    Brighton, UK
    Posts
    2,006
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It might be that check for "script.readyState" that's throwing it off:

    Code:
    if (script.readyState) {}
    You're not testing if the property exists, you're just testing that it's a "truthy" value. What happens if you completely get rid of that check?

    Also, it might be worth peaking into the jQuery source:

    Code JavaScript:
    script.onload = script.onreadystatechange = function(){
        if ( !done && (!this.readyState ||
                this.readyState === "loaded" || this.readyState === "complete") ) {
            done = true;
            success();
            complete();
     
            // Handle memory leak in IE
            script.onload = script.onreadystatechange = null;
            if ( head && script.parentNode ) {
                head.removeChild( script );
            }
        }
    };
    James Padolsey
    末末末末末末末末末末末末末末末末末末末
    Awesome JavaScript Zoomer (demo here)
    'Ajaxy' - Ajax integration solution (demo here)

  6. #6
    SitePoint Member
    Join Date
    May 2009
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I haven't been able to reproduce this issue with my script loader LABjs, which fundamentally uses very similar logic.

    I suspect that maybe what is happening is that your script isn't actually fully loading (for whatever reason) and that's why the flakiness of the load handler not being called sometimes.

    It might be good to inspect the dom and the page (with a console or whatever) when you have an occurence of the handler not firing, and see if the script in question really did load or not.

  7. #7
    SitePoint Enthusiast
    Join Date
    Sep 2008
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @JimmyP
    Thanks for the suggestions, but if I remove that check for "readyState" then there would be no way to tell the difference between the browser implementations.

    Looking at that jQuery code snippet you provided made partial sense, it looks like they have a 'done' variable to check when the script has loaded for WebKit/Gecko browsers and then also check it against the IE specific readyState object to make sure it returns the relevant values.

    Problem is that I can't work out where 'done' gets its value from in the jQuery code (simply because there is so much of it and keeping track of it is a bit of a nightmare).

    @shadedecho
    I check the page resources using Chrome/WebKit's "resources" tab and it shows that both the scripts load fine? but for whatever reason the 'onload' event just doesn't fire.


    M.

  8. #8
    SitePoint Member
    Join Date
    May 2009
    Posts
    3
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Can you provide a test page that demonstrates (at least intermittently) this bug with simple code and no extras in the way? I'd like to be able to reproduce it, but I haven't yet been able to.

    Also, what exact version of Webkit are you testing with? Safari 4? What platform?

  9. #9
    SitePoint Enthusiast
    Join Date
    Sep 2008
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    No problem i'll look at getting this together for you today.

    Thanks for your help!

    M.

  10. #10
    SitePoint Enthusiast
    Join Date
    Sep 2008
    Posts
    48
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, I stand corrected.

    Just as I was getting together an example, I discovered that the loadScript IS working fine and running the callback function, but the callback function then has a call to jQuery's
    Code:
    $(document).ready()
    and that method is the one that doesn't seem to run every time.

    I then went ahead and created a test page and found that once I had stripped out nearly all of the code (so we could concentrate on testing just the loadScript and jQuery Dom Ready) it turns out that no matter what I do (whether I load the page directly, link to it, refresh it while I'm on it) the Dom Ready event doesn't fire!

    In my example I'm trying to load the script "Library.php" and although it's a php file it actually just concatenates the jQuery library and then my Js code and returns a single Js file. I've also tested it by calling a js file called "testing.js" which its source code was both the jQuery library again followed with my Js code (just in case it was the PHP causing a problem) - but this still gave the same results.

    I'm on Windows XP and the specific Chrome/WebKit versions are as follows...

    Safari 4.0.1 (531.21.10)
    Chrome (4.0.288.1 dev)

    Example files attached.

    Any ideas or help greatly appreciated.

    Thank you!

    M.
    Attached Files Attached Files


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •