I've held it as an "absolute truth" for a long time that doing:
let img = new Image();
img.src = '... some url ...'
img.onload = function() { console.log('onload') }
was wrong, because the .onload handler might not be called. Same thing for attaching a handler using .addEventListener('load', function() ... ) after setting .src: it might not work. (see this example answer stating this: "... Add event listener before assigning a value to the src attribute ...")
Context for this question: I've found an example of setting .src before calling .addEventListener in the popular p5.js library, specifically here. I would like to fix this and submit a PR. However, I would also like to create a unit test that fails with the current code (setting .src = before calling .addEventListener) and passes with my fix.
However! I haven't been able to actually see under which circumstances setting .src before actually fails...!
Here is some code to demonstrate what I mean:
(function f() {
let i = new Image();
i.src = '//placekitten.com/10/10';
document.querySelector('body').appendChild(i);
let out = 0;
for(let i = 0; i < 1000000000; i++) { out *= i * 100 - out * 2; } // just to delay
i.onload = function() { console.log('onload') }
i.addEventListener('load', function() { console.log('load event') });
})();
The 1000000000-iteration loop takes a few seconds to complete, as I'm trying to get the Image element to be added to the DOM and the image URL to be loaded early enough that the .onload and .addEventListener handlers would fail... But they work!
I tried with a very short data URL instead of placekitten.com, same result. I tried loading the placekitten.com and the data URL images before running my test code (to make sure those images are cached), but that doesn't work either.
The only way I can get the .onload and .addEventListener handlers to not be called is to wrap them in a setTimeout...
Is JavaScript's single-threadneness invalidating the "truth" that .src should always be set after setting event listeners? Or is this a change that happened in modern browsers, and it used to be true in older browsers that setting .src before attaching listeners would sometimes fail? Thanks!
The order doesn't matter. The load event is always fired asynchronously (queued on the event loop by the loading algorithm), after the synchronous execution has completed, and will evaluate which event listeners are installed and need to be executed only then.
Given the answer that you linked and especially image.onload event and browser cache / jQuery callback on image load (even when the image is cached), it appears older browsers might have fired the event synchronously (or not at all) if the image was loaded from the cache.