Waiting on Lazy Loaded objects without lockup?

2019-03-01 21:42发布

问题:

I already have code which lazy loads scripts on request. My issue now is waiting to execute certain code until the object becomes available. I can't use a setTimeout() because it does not block execution.

So what is a good way to 'wait' for a load, without locking the browser?

Again, can't use raw setTimeout().

回答1:

Assuming you control the contents of your script, you can put some code to execute at the bottom of your lazy loaded script to indicate to the main page that the script has loaded. For example, in your page you can do something like this:

var loadingScripts = 0;
var loadScript = function() {
    // Do what you need to do to load the script...

    loadingScripts++;
}

var loadedScript = function() {
    loadingScripts--;
    if (loadingScripts == 0) {
        // Kick off execution of code that requires the lazy loaded scripts.
    }
}

Then in your script, you'd add this code to the bottom:

loadedScript();

You can spice this example up with an array instead of an integer (to keep track of which specific scripts have loaded). You could also use an object instead to associate particular function calls with the completion of particular scripts. I kept my example simple, but ask if you want me to show how to do extend the code.


Here is how you can use a callback to continue execution of specific code upon loading of a script (again, assuming you control the scripts themselves).

var scriptCallbacks = {}
var loadScript = function(scriptname, callback) {
    // Do what you need to load scriptname

    scriptCallbacks[scriptname] = callback;
}

var loadedScript = function(scriptname) {
    (scriptCallbacks[scriptname])();
}

Then when you want to load a script, you do something like this...

var callback = function() {
    // Write exactly what you want executed once your script is loaded
}

loadScript("MyScript.js", callback);

And again, in your lazy loaded script, just add this code to the bottom to inform your callback to fire:

loadedScript("MyScript.js");


回答2:

I'd actually do it differently than Daniel mentioned. All elements fire a load event when they have loaded, and a Javascript file is loaded after it has evaluated the content. So you can set an event handler to continue execution after their available:

var loadScript = function(fileName, callback) {
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = fileName;

    script.onload = callback;
    script.onreadystatechange = function() {
        if(this.readyState == 'complete') {
            callback();
        }
    };
    head.appendChild(script);
};

And an example usage:

var bar = function() {
    Foo.baz();
};
if(!window.Foo) {
    loadScript('Foo.js',bar);
} else {
    bar();
}