javascripthtmlasync-awaitscript-tagios-web-app

How can I wait for <script> appended to body to finish executing


When the user clicks a button I need to append to my body an external script. This is the requirement.

Rookie question. Let's say that the external library creates a window.newLib variable. How can I be notified when the newLib variable is ready for me to use?

I tried this but onload does not get called:

  const script = document.createElement('script');
  script.innerHTML = 'window.test = 1; console.log("test defined.");';
  script.onload = "console.log('onload called.', window.test)"
  script.async = false;
  document.body.appendChild(script);

This works but it seems dirty to me. Is there a better way?

const injectScript = () => {
  const script = document.createElement('script');
  script.innerHTML = 'setTimeout(() => {window.test = 1},10500); console.log("test defined.");';
  script.async = false;
  document.body.appendChild(script);
}

const nap = ms => new Promise(res => setTimeout(res, ms));

const maxAttempts = 100;
const msNap = 100; // 10s timeout

const start = async () => {
  injectScript();
  let id = 0;
  while (true) {
    if (++id === maxAttempts) {
      throw(`Lib took too long to load: ${id * msNap}ms`);
    }
    if (window.test) break;
    await nap(msNap);
  }
  console.log('External lib correctly loaded.');
};
start();

Solution

  • Thanks to @Ultimater. This seems to work as expected:

    const script = document.createElement('script');
    script.src = 'data:text/html,id = 0;while(true){ if(++id==1000000) break;} window.test = 1; console.log("test defined.");';
    script.onload = () => console.log('onload called.', window.test);
    document.body.appendChild(script);