1

I have a website which has two files; main.js and loading.js

loading.js waits for DOMContentLoaded, then clears a loading screen cover.

main.js also waits for DOMContentLoaded, but also waits for loading.js to finish its DOMContentLoaded, then executes some more code.

I need to write some code (possibly using Promises?) which allows this to happen.

Here is my code:

loading.js

document.addEventListener('DOMContentLoaded', () => {
    var loadingCover = document.querySelector('#loading-cover');
    loadingCover.style.display = 'none';
});

main.js

document.addEventListener('DOMContentLoaded', () => {
    /* Wait for loading.js */
    console.log("Do stuff");
});

I've done some research with Promises, but I can't wrap my head around how they could work in this situation.

I've tried using a Promise which is resolved inside loading.js. main.js then waits for that Promise to be resolved before executing its own code.

Ideally, this would be the code:

loading.js

const loadingPromise = new Promise();
document.addEventListener('DOMContentLoaded', () => {
    var loadingCover = document.querySelector('#loading-cover');
    loadingCover.style.display = 'none';
    loadingPromise.resolve();
});

main.js

/* Terrible example */
loadingPromise.addEventListener('resolve', () => {
    console.log("Do stuff");
});
notsoscottishscot
  • 350
  • 1
  • 4
  • 11
  • You can have 2 handle event attached to the same element and if I remember properly they are executed in order thus should be enough to link first the script for loading.js and later that for main.js No need promises. – Nick Jun 17 '23 at 23:55

1 Answers1

1

One way to do is by creating a Promise, then saving the resolve function to be later called like this:

//
// createPromise() returns an object containing the promise
// itself and the function to be called in order to resolve
// said promise
//
function createPromise() {
    let ret = {}

    ret.promise = new Promise((resolve) => {
        ret.resolve = resolve
    })

    return ret
}

window.main_promise = createPromise()

document.addEventListener('DOMContentLoaded', () => {
    var loadingCover = document.querySelector('#loading-cover');
    loadingCover.style.display = 'none';

    // add some artificial delay
    setTimeout(window.main_promise.resolve, 1000);
});

In loading.js:

document.addEventListener('DOMContentLoaded', async () => {
    /* Wait for loading.js */
    await window.main_promise.promise;

    console.log("Do stuff");
});

This will block execution of console.log("Do stuff"); until window.main_promise.resolve(); is called somewhere in code.

Of course, main.js needs to be loaded before loading.js in order for this to work.

Marco
  • 7,007
  • 2
  • 19
  • 49
  • 1
    This answer is perfect! Thank you. I'll accept asap – notsoscottishscot Jun 17 '23 at 23:54
  • 1
    You're quite welcome :-) glad I could help! – Marco Jun 17 '23 at 23:55
  • Convoluted solution – Nick Jun 17 '23 at 23:58
  • @Nick You don't know what OP is going for, using something that is asynchronous in nature, `Promise`s are the way to go. So no, not convoluted, only if we're dealing with synchronous stuff, then it would be indeed convoluted ; but we don't know that. `Promise`s work regardless, it doesn't matter whether the code is synchronous or not. – Marco Jun 18 '23 at 00:02
  • The DomContentLoaded events are asynnchronous by default. The 2 callback are called in an async way thereby the code inside is executed in order by default. No need Promises – Nick Jun 18 '23 at 00:07
  • @Nick You're repeating yourself. You don't know what OP is doing in the first callback, so it could (and I assume it is) be asynchronous. You cannot (well, you can, but that's a bit messy and old) deal with that without using Promises. – Marco Jun 18 '23 at 00:09
  • Ok, you say the code inside the DomContentLoaded event. Yes, you are right, if the code inside is asynchronous he needs Promises or he could load the second script with "dynamic script loading" when the async code inside the first DOMContent loaded handler termined – Nick Jun 18 '23 at 00:14