0

I return within an ajax request a custom html tag:

<eval-script src="script1.js"></eval-script>
<eval-script src="script2.js"></eval-script>
<eval-script src="script3.js"></eval-script>

Then I parse the response and store all script executions in an array (arrow functions):

const evalArray = [];

const getScript = function(src, dfd) {
    $.getScript(src)
        .done(function() {
            dfd.resolve();
        })
        .fail(function() {
            dfd.reject();
        });
}

const evalScripts = document.querySelectorAll("eval-script");
for (const script of evalScripts) {
    const src = script.getAttribute("src");
    evalArray.push((dfd) => getScript(src, dfd));
};

After that I iterate through the array and try to wait for script to be loaded (non-deferred, synchronous):

            evalArray.forEach((func) => { 
                const dfd = $.Deferred();
                func(dfd);
                while (dfd.state() === "pending") {
                    console.log("wait for resolve (" + dfd.state() + "): " + func);
                };
                return;
            });

This is done because I want the scripts to execute in the submitted order and they could rely on the previous script. Also I want to execute some script after that that relies on the scripts being loaded.

Unfortunatly I can see $.getScript is requesting the script, and the scripts response headers are shown in browsers network tab, but there is no content and the promises done or fail are not executed.

The scripts can be opened by url in browser with no problem. Also I can execute "$.getScript('script1.js')" in console without any problem.

I do not want to use synchronous Ajax because that is deprecated option in jquery. Also I have no problem with promise setup, but getScript is not executing as expected.

Can someone please help?

jfriend00
  • 683,504
  • 96
  • 985
  • 979
Darth Sonic
  • 105
  • 7
  • 1
    @jfriend00 I've been using that duplicate for years, it might not have aged well as promises have become popular. Maybe someone should add an answer that shows how to do it with promises. – Barmar Apr 17 '22 at 00:58
  • @jfriend00 If you have one I'll update my link. – Barmar Apr 17 '22 at 02:00
  • The only answer I see I could replicate is using async = false option, but that is deprecated. I tried promise.all but either it did not work or I used it wrong. – Darth Sonic Apr 18 '22 at 06:34
  • @Barmar - I added a modern answer to that [dup](https://stackoverflow.com/questions/1151598/how-to-make-all-ajax-calls-sequential/71933371#71933371). It kind of gets lost in all the other old, outdated answers to that question, but at least it's there now. – jfriend00 Apr 20 '22 at 16:49

2 Answers2

0

My code now looks like this according to @jfriend00 suggestion:

    async function loadScripts() {
        const evalScripts = document.querySelectorAll("eval-script");
        for (const script of evalScripts) {
            const src = script.getAttribute("src");
            await $.getScript(src);
            console.log("getScript done: " + src);
        }
    }

    loadScripts().then(result => {
        console.log("all done loading scripts: " + result);
    }).catch(err => {
        console.log(err);
    });

    console.log("eval done!");

Unfortunately the script is not waiting for all scripts to be loaded as console output is:

eval done!
getScript done: script.js
getScript done: script2.js
getScript done: script3.js
getScript done: script4.js
getScript done: script5.js
all done loading scripts: undefined

How do I make the script wait for all scripts to be loaded?

And as I see, async await is ECMA2016 feature. How widely is is supported by browsers?

Darth Sonic
  • 105
  • 7
0

Final solution:

My ajax request is now calling a async function on success (done promise):

$.ajax({

    ...

}).done(function(data, textStatus, jqXHR) {

    onSuccess();

})

Within onSuccess function I placed async code from above, but I am awaiting the promise in addition:

async function onSuccess() { 

    async function loadScripts() {
        const evalScripts = document.querySelectorAll("eval-script[src]");
        for (const script of evalScripts) {
            const src = script.getAttribute("src");
            await $.getScript(src);
        }
    }
    
    await loadScripts();

}

This way I can access and execute each object/function from the evaluated scripts directly after calling "await loadScripts()".

My thanks goto @jfriend00 pushing me the right way and clarifying async await execution in javascript.

Darth Sonic
  • 105
  • 7