Resource loading: onload and onerror

The browser allows to track the loading of external resources – scripts, iframes, pictures and so on.

There are two events for it:

  • onload – successful load,
  • onerror – an error occured.

Loading a script

Let’s say we need to call a function that resides in an external script.

We can load it dynamically, like this:

let script = document.createElement('script');
script.src = "my.js";


…But how to run the function that is declared inside that script? We need to wait until the script loads, and only then we can call it.


The main helper is the load event. It triggers after the script was loaded and executed.

For instance:

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

// can load any script, from any domain
script.src = ""

script.onload = function() {
  // the script creates a helper function "_"
  alert(_); // the function is available

So in onload we can use script variables, run functions etc.

…And what if the loading failed? For instance, there’s no such script (error 404) or the server or the server is down (unavailable).


Errors that occur during the loading (but not execution) of the script can be tracked on error event.

For instance, let’s request a script that doesn’t exist:

let script = document.createElement('script');
script.src = ""; // no such script

script.onerror = function() {
  alert("Error loading " + this.src); // Error loading

Please note that we can’t get error details here. We don’t know was it error 404 or 500 or something else. Just that the loading failed.

Other resources

The load and error events also work for other resources. There may be minor differences though.

For instance:

<img>, <link> (external stylesheets)
Both load and error events work as expected.
Only load event when the iframe loading finished. It triggers both for successful load and in case of an error. That’s for historical reasons.


Pictures <img>, external styles, scripts and other resources provide load and error events to track their loading:

  • load triggers on a successful load,
  • error triggers on a failed load.

The only exception is <iframe>: for historical reasons it always triggers load, for any load completion, even if the page is not found.

The readystatechange event also works for resources, but is rarely used, because load/error events are simpler.


importance: 4

Normally, images are loaded when they are created. So i when we add <img> to the page, the user does not see the picture immediately. The browser needs to load it first.

To show an image immediately, we can create it “in advance”, like this:

let img = document.createElement('img');
img.src = 'my.jpg';

The browser starts loading the image and remembers it in the cache. Later, when the same image appears in the document (no matter how), it shows up immediately.

Create a function preloadImages(sources, callback) that loads all images from the array sources and, when ready, runs callback.

For instance, this will show an alert after the images are loaded:

function loaded() {
  alert("Images loaded")

preloadImages(["1.jpg", "2.jpg", "3.jpg"], loaded);

In case of an error, the function should still assume the picture “loaded”.

In other words, the callback is executed when all images are either loaded or errored out.

The function is useful, for instance, when we plan to show a gallery with many scrollable images, and want to be sure that all images are loaded.

In the source document you can find links to test images, and also the code to check whether they are loaded or not. It should output 300.

Open a sandbox for the task.

The algorithm:

  1. Make img for every source.
  2. Add onload/onerror for every image.
  3. Increase the counter when either onload or onerror triggers.
  4. When the counter value equals to the sources count – we’re done: callback().

Open the solution in a sandbox.

Tutorial map


read this before commenting…
  • You're welcome to post additions, questions to the articles and answers to them.
  • To insert a few words of code, use the <code> tag, for several lines – use <pre>, for more than 10 lines – use a sandbox (plnkr, JSBin, codepen…)
  • If you can't understand something in the article – please elaborate.