catch every script load-complete event with javascript or jQuery

Learn catch every script load-complete event with javascript or jquery with practical examples, diagrams, and best practices. Covers javascript, jquery, load development techniques with visual expl...

Catching Every Script Load-Complete Event in JavaScript and jQuery

Hero image for catch every script load-complete event with javascript or jQuery

Learn how to reliably detect when dynamically loaded scripts have finished executing, ensuring your application logic runs at the correct time.

In web development, dynamically loading JavaScript files is a common practice for improving performance, managing dependencies, or implementing modular architectures. However, knowing precisely when a dynamically loaded script has finished executing can be challenging. This article explores various techniques in both plain JavaScript and jQuery to reliably detect script load-complete events, helping you avoid race conditions and ensure your application behaves as expected.

The Challenge of Dynamic Script Loading

When you add a <script> tag to the DOM, the browser fetches and executes the script. For static scripts defined directly in your HTML, the execution order is generally predictable. However, when scripts are added dynamically via JavaScript, their loading and execution are asynchronous. This means that code immediately following the script injection might run before the dynamically loaded script has fully parsed and executed, leading to errors if your subsequent code depends on variables or functions defined in the loaded script.

sequenceDiagram
    participant Browser
    participant YourScript
    participant DynamicScript

    YourScript->>Browser: Create <script> element
    YourScript->>Browser: Append <script> to DOM
    Browser->>DynamicScript: Request script file
    Note over Browser,DynamicScript: Network latency
    DynamicScript-->>Browser: Script content received
    Browser->>Browser: Parse and execute DynamicScript
    Note over YourScript: YourScript continues execution
    YourScript->>YourScript: Attempt to use DynamicScript's functions (may fail)
    Browser->>YourScript: Dispatch 'load' event (after execution)
    YourScript->>YourScript: Now safe to use DynamicScript's functions

Sequence of dynamic script loading and potential race condition

Native JavaScript Solutions

Modern browsers provide events that allow you to monitor the state of dynamically loaded scripts. The primary events to consider are load and error.

function loadScript(url, callback) {
  const script = document.createElement('script');
  script.type = 'text/javascript';
  script.src = url;

  script.onload = function() {
    console.log(`Script ${url} loaded successfully.`);
    if (callback) {
      callback(null, script);
    }
  };

  script.onerror = function() {
    console.error(`Error loading script ${url}.`);
    if (callback) {
      callback(new Error(`Failed to load script: ${url}`));
    }
  };

  document.head.appendChild(script);
}

// Usage:
loadScript('https://example.com/my-library.js', function(error, script) {
  if (error) {
    console.error('Failed to load library:', error);
  } else {
    console.log('my-library.js is now available!');
    // You can now safely use functions/variables from my-library.js
  }
});

Loading a script using native JavaScript onload and onerror events

jQuery's Approach to Script Loading

jQuery provides a convenient method, $.getScript(), which simplifies the process of loading and executing JavaScript files asynchronously. It internally handles the creation of the <script> element and attaches event listeners.

$.getScript('https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js')
  .done(function(script, textStatus) {
    console.log(`Script loaded: ${textStatus}`); // textStatus will be 'success'
    console.log('jQuery UI is now available!');
    // You can now safely use jQuery UI functions
    $('body').append('<div id="draggable" style="width:100px;height:100px;background:red;"></div>');
    $('#draggable').draggable();
  })
  .fail(function(jqxhr, settings, exception) {
    console.error('Error loading script:', exception);
  });

Loading a script using jQuery's $.getScript() method

Handling Multiple Scripts and Dependencies

When you need to load multiple scripts, especially if they have dependencies on each other, managing the load order becomes crucial. Promises (native or jQuery's deferred objects) are excellent for this.

Native JavaScript (Promises)

function loadScriptPromise(url) { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.type = 'text/javascript'; script.src = url;

script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Failed to load script: ${url}`));

document.head.appendChild(script);

}); }

// Load scripts sequentially (dependency: script2 needs script1) loadScriptPromise('https://example.com/script1.js') .then(() => loadScriptPromise('https://example.com/script2.js')) .then(() => { console.log('Both script1.js and script2.js are loaded and ready!'); // Safely use functions from both scripts }) .catch(error => { console.error('One or more scripts failed to load:', error); });

// Load scripts in parallel (no dependencies between them) Promise.all([ loadScriptPromise('https://example.com/libA.js'), loadScriptPromise('https://example.com/libB.js') ]) .then(() => { console.log('Both libA.js and libB.js are loaded and ready!'); }) .catch(error => { console.error('One or more parallel scripts failed to load:', error); });

jQuery (Deferred/Promises)

// Load scripts sequentially $.getScript('https://example.com/jquery-plugin1.js') .then(function() { return $.getScript('https://example.com/jquery-plugin2.js'); }) .done(function() { console.log('Both jQuery plugins loaded and ready!'); }) .fail(function(jqxhr, settings, exception) { console.error('One or more jQuery plugins failed to load:', exception); });

// Load scripts in parallel $.when( $.getScript('https://example.com/utility1.js'), $.getScript('https://example.com/utility2.js') ) .done(function() { console.log('Both utility scripts loaded in parallel and ready!'); }) .fail(function(jqxhr, settings, exception) { console.error('One or more parallel utility scripts failed to load:', exception); });