Yep. This surprised me as well but it is all there in black and white on the MDM Article for the <img> element.
I've always just plonked a onerror()
handler on my image elements when I thought they needed it but it turns out that it doesn't fire in all erroneous circumstances. In fact, there is no way to write robust code that handles user-supplied images by handling events.
For instance, the following does not work if the src is a data url that does not decode properly.
// this does not work function createImageFromSrc(src) { const image = new Image() image.onload = () => { console.log("Image loaded - happy days") doSomethingWithTheImage(image) } image.onerror = () => { console.log("Image failed") showAnErrorToTheUser() } image.src = src }
This is a problem if, for instance, you want to support drag and drop or user-selected files. If the user selects a non-image file then neither onload
or onerror
will fire and your application will be in a weird state.
The solution if you need to dynamically create images is to use the image.decode()
method which returns a promise which will be rejected if the image decoding fails for any reason.
// this is the way function createImageFromSrc(src) { const image = new Image() image.src = src image.decode().then(()=>{ console.log("Image loaded just as I promised") doSomethingWithTheImage(image) }) .catch((decodeError)=>{ console.log("Sorry Dave, I could not decode this image:", decodeError) showAnErrorToTheUser() }) .finally(()=>{ console.log("This happens either way") }) }
Hopefully this helps somebody avoid the 45 minutes it took me to figure out what was going wrong in my code.