Home > database >  Can image load event be synchronous, or will it always be asynchronous?
Can image load event be synchronous, or will it always be asynchronous?

Time:10-18

Let's say I have the following code:

let img = document.createElement("img");
img.addEventListener("load", function() {
    alert("Loaded!");
});
img.src = external_string; // Can "load" fire here?

The question is - if the image in external_string is already in browser cache, or maybe is base64 encoded, or whatever - can it so happen that the load event is called immediately at the same line as src is being assigned?

Note: I actually want it to be asynchronous because I want to set up a few more things before the load event gets fired. But if there is a chance that it might get fired synchronously then I need to put in extra work to postpone that.

I could not find this subtlety explained in any document, but practical tests always call the event asynchronously.

CodePudding user response:

You can use the decode() method to wait for images to be ready. Even if the image loads immediately, queuing the promise micro-task will always ensure code runs after the promise resolves

Promise handlers .then/.catch/.finally are always asynchronous.

Even when a Promise is immediately resolved, the code on the lines below .then/.catch/.finally will still execute before these handlers.

// Base64 data URI requires no loading time
const red_dot = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

const img = document.createElement("img");
img.src = red_dot;
img.decode().then(() => {
  console.log("img ready, this will log second");
  document.body.append(img);
});
console.log("img loading, this will log first");

Keep in mind that you cannot call decode() before setting src.


The load event will also always trigger and a listener can be added at any time however since it relies on the event loop, control over the order of operations is non-deterministic. That being said, any procedural code you add after setting the src will always execute before the event handler fires.

// Base64 data URI requires no loading time
const red_dot = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";

const img = document.createElement("img");
img.addEventListener("load", () => {
  console.log("img ready, this will log second");
  document.body.append(img);
});
img.src = red_dot;
console.log("img loading, this will log first");

  • Related