0

I’m trying to execute an action when all the scripts on the page have loaded.

Sync scripts execute as soon as their DOM element is parsed. But async scripts have a DOM element available before the script even starts loading and long before it starts executing. I want to be able to hook into the lifecycle of these script elements.

I tried setting a load listener on async scripts but the load event will not fire if I listen for it on a script that has already executed. So I need to attach it only to scripts that have not yet executed. But there seems to be no property indicating the load/execution state of a script. <img> tags have .complete and the document has .readyState but it seems scripts don’t have any property like those.

I thought I could wait for load on window but that would mean also awaiting images and the like, which seems wasteful when I’m only interested in scripts (meaning my action would be executed much later than I’d like). I also looked into the ready states of the document but it seems those don’t represent the execution state of async scripts (async scripts can execute either before or after the document becomes interactive).

Note 1: I know I could just change the scripts themselves to call a callback or set a global whenever they execute but I’m not looking for these kinds of answers. What I’m looking for is a generic solution that works without changing the scripts themselves.

Note 2: Also, the script wanting to await the async scripts is also, itself, an async script. If it weren’t I could just put it before all the async scripts and attach a load listener as described above. But I don’t want to degrade performance by loading a sync script, even if it’s small.

Essentially there are the following three possible scenarios:

  1. My script runs before all other async scripts (in which case the load listener would work).
  2. My script is executing somewhere between other async scripts (in which case I’d have to know which ones have already executed and which ones have yet to execute).
  3. My script is executing last (in which case I don’t need to await anything).

I can force scenario 1 (by making my script sync and putting it before all others) or scenario 3 (by awaiting the window load event) at the expense of performance but I can’t seem to solve the problem for scenario 2, which is the general case.

3
  • I guess I’m asking this question because I want to be sure I’m not missing something. Introducing the async attribute, withut introducing a readyState or complete property to go with it, seems like a massive oversight to me… Commented Jul 2, 2020 at 9:08
  • > “If it weren’t I could just put it before all the async scripts and attach a load listener as described above” — Not sure this would even work, since here, too, we have a race condition between my script and the DOM elements of other script. Maybe MutationObservers could inform me when new script elements have been parsed. Don’t know if they work in the parsing phase of the document, though. Commented Jul 3, 2020 at 15:38
  • It seems the situation has improved somewhat when limiting yourself to ESModules and are prepared to rewrite your <script> tags: stackoverflow.com/a/78339548/11940 Commented Apr 17, 2024 at 11:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.