Skip to content Skip to sidebar Skip to footer

HTML Load Order And Dynamically Added JS Files

I add some JS files dynamically to my HTML Header and I want to guarantee that my JS files finish loading before I continue to render my Body. Events like load or DOMContentLoaded

Solution 1:

We could question whether loading scripts following some user action, is such a good idea. You could instead load the relevant HTML content from the server (which could include script tags), if you really want to have a one-page experience, or else initiate a navigation, where again the server would get clues via HTTP request on what to generate next.

But, if we stick with this pattern, I would suggest using the onload property of script elements, and to use promises for awaiting all scripts to have been loaded.

Here is some code you could use. This demo loads two JS files after an AJAX call has come back with a response: one for the immutablejs library, the second for the momentjs library.

A new Promise will resolve when the script's load event fires, and Promise.all will resolve when this has happened for all scripts.

For the purpose of demo I replaced the URL with a mock, and also tampered with the response in order to produce a response as you have it:

// dummy server, just for demo
let url = "https://jsonplaceholder.typicode.com/todos/1";
console.log("Launching initial HTTP request...");
$.get(url).then(function (response) {
    console.log("Received response. Loading scripts...");
    // Overwriting the response with mock data:
    response = {
        immutable: "https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.min.js",
        moment: "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js"
    };
    return Promise.all(Object.values(response).map(function (scriptName) {
        return new Promise(function (resolve, reject) { 
            //Adding of the script(s)
            let myScript = document.createElement("script");
            myScript.setAttribute("src", scriptName);
            myScript.onload = resolve;
            myScript.onerror = reject;
            document.head.appendChild(myScript);
            //
        });
    }));
}).then(function () {
    // All code that depends on the loaded scripts should be here, or called from here
    console.log("All scripts loaded:");
    console.log("Immutable: ", typeof Immutable);
    console.log("moment: ", typeof moment);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Remark: the async: false option is deprecated. It is not good practice either. Instead use the Promise that jQuery returns for $.ajax, $.get, ...etc, and chain a then call where you continue processing the result (instead of a success handler). And on once you arrive in the world of promises, you'll find that using async and await syntax can simplify code.


Post a Comment for "HTML Load Order And Dynamically Added JS Files"