user11807902
user11807902

Reputation: 65

Confusion with how asynchrony happens in this code

I new to JS and was learning callbacks and how asynchrony happens with the callbacks. I came across code on https://javascript.info/callbacks which is

function loadScript(src) {
  let script = document.createElement('script');
  script.src = src;
  document.head.append(script);
}

loadScript('/my/script.js');
// the code below loadScript doesn't wait for the script loading to finish
// ...

So, it is said that loadScript function is executed asynchronously but WHY? as far as I know asynchony happens with functions like setTimeOut or xhr object which are executed via event loop. So, why if we only create element in loadScript function, it is executed asynchronously

Upvotes: 0

Views: 65

Answers (3)

BenM
BenM

Reputation: 53198

The wording in the article is poorly written.

The function is called “asynchronously,” because the action (script loading) finishes not now, but later.

The function call is synchronous. The loading of /my/script.js is asynchronous, because JS does not wait for the file to be loaded before continuing with its call stack. Any script elements created using createElement are loaded asyncrhonously - you can read more about it here:

Dynamically inserted scripts (using document.createElement()) load asynchronously by default

The following is a better example of asynchronous calling:

let script = document.createElement('script');

script.src = '/my/script.js';
document.head.append(script);

script.onload = function()
{
  // Any code defined inside here is now truly asynchronous.
  // It will not be called until /my/script.js has been loaded.
}

Upvotes: 4

slebetman
slebetman

Reputation: 113866

Because of how the <script> tag works. Browsers will load the <script> tag synchronously except when:

  1. it has an async tag set to true

  2. it has been created using document.createElement()

So the loadScript function does the second part.

see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script

Upvotes: 1

Christian Vincenzo Traina
Christian Vincenzo Traina

Reputation: 10384

Why should it wait? You are adding an element to DOM, which performs a HTTP request. If we should wait every request performed by DOM elements then out page would be incredibly slow (Yes, I'm simplifying).

By the way, you have to wait that the onload event is fired on the element, then you can be sure that the script has been loaded:

function loadScript(src, cb) {
  let script = document.createElement('script');
  script.src = src;
  script.onload = cb;
  script.onerror = cb;
  document.head.append(script);
}

loadScript('/my/script.js', function (response) {
   // Your asynchronous code here
});

In this example I used callback, since it's the easier to understand. But you can easily convert it to Promises or async / await:

function loadScript(src) {
  let script = document.createElement('script');
  script.src = src;
  document.head.append(script);
  return new Promise((res, rej) => { // ES6 only
    script.onload = res;
    script.onerror = rej;
  });
}

loadScript('/my/script.js')
.then(() => {
   // Your asynchronous code here
})
.catch(() => {
  // Error handling
});

Or:

(async function () {
  await loadScript('/my/script.js');
  // Your async code here
})();

Where the definition of loadScript is like above

Upvotes: 1

Related Questions