Waiting on Lazy Loaded objects without lockup?

笑着哭i 提交于 2019-12-02 07:50:59

问题


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();
}



回答3:


Based on the answer of seanmonstar, I've found this async/await solution to work nicely. It resolves immediately if the script was already loaded previously, or it resolves asynchronously at a later time once the script was downloaded.

static async loadScript(url){

    return new Promise( resolve => {

        const element = document.getElementById(url);

        if(element){
            resolve();
        }else{
            const script = document.createElement("script");

            script.id = url;

            script.onload = () => {
                resolve();
            };
            script.src = url;

            document.body.appendChild(script);
        }
    });

}

And it's used like this:

await loadScript("../libs/geopackage/geopackage.js");


来源:https://stackoverflow.com/questions/903012/waiting-on-lazy-loaded-objects-without-lockup

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!