[javascript] How to create a JavaScript callback for knowing when an image is loaded?

I want to know when an image has finished loading. Is there a way to do it with a callback?

If not, is there a way to do it at all?

This question is related to javascript image callback loading

The answer is


Life is too short for jquery.

_x000D_
_x000D_
function waitForImageToLoad(imageElement){_x000D_
  return new Promise(resolve=>{imageElement.onload = resolve})_x000D_
}_x000D_
_x000D_
var myImage = document.getElementById('myImage');_x000D_
var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"_x000D_
_x000D_
myImage.src = newImageSrc;_x000D_
waitForImageToLoad(myImage).then(()=>{_x000D_
  // Image have loaded._x000D_
  console.log('Loaded lol')_x000D_
});
_x000D_
<img id="myImage" src="">
_x000D_
_x000D_
_x000D_


these functions will solve the problem, you need to implement the DrawThumbnails function and have a global variable to store the images. I love to get this to work with a class object that has the ThumbnailImageArray as a member variable, but am struggling!

called as in addThumbnailImages(10);

var ThumbnailImageArray = [];

function addThumbnailImages(MaxNumberOfImages)
{
    var imgs = [];

    for (var i=1; i<MaxNumberOfImages; i++)
    {
        imgs.push(i+".jpeg");
    }

    preloadimages(imgs).done(function (images){
            var c=0;

            for(var i=0; i<images.length; i++)
            {
                if(images[i].width >0) 
                {
                    if(c != i)
                        images[c] = images[i];
                    c++;
                }
            }

            images.length = c;

            DrawThumbnails();
        });
}



function preloadimages(arr)
{
    var loadedimages=0
    var postaction=function(){}
    var arr=(typeof arr!="object")? [arr] : arr

    function imageloadpost()
    {
        loadedimages++;
        if (loadedimages==arr.length)
        {
            postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
        }
    };

    for (var i=0; i<arr.length; i++)
    {
        ThumbnailImageArray[i]=new Image();
        ThumbnailImageArray[i].src=arr[i];
        ThumbnailImageArray[i].onload=function(){ imageloadpost();};
        ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
    }
    //return blank object with done() method    
    //remember user defined callback functions to be called when images load
    return  { done:function(f){ postaction=f || postaction } };
}

Image.onload() will often work.

To use it, you'll need to be sure to bind the event handler before you set the src attribute.

Related Links:

Example Usage:

_x000D_
_x000D_
    window.onload = function () {_x000D_
_x000D_
        var logo = document.getElementById('sologo');_x000D_
_x000D_
        logo.onload = function () {_x000D_
            alert ("The image has loaded!");  _x000D_
        };_x000D_
_x000D_
        setTimeout(function(){_x000D_
            logo.src = 'https://edmullen.net/test/rc.jpg';         _x000D_
        }, 5000);_x000D_
    };
_x000D_
 <html>_x000D_
    <head>_x000D_
    <title>Image onload()</title>_x000D_
    </head>_x000D_
    <body>_x000D_
_x000D_
    <img src="#" alt="This image is going to load" id="sologo"/>_x000D_
_x000D_
    <script type="text/javascript">_x000D_
_x000D_
    </script>_x000D_
    </body>_x000D_
    </html>
_x000D_
_x000D_
_x000D_


Not suitable for 2008 when the question was asked, but these days this works well for me:

async function newImageSrc(src) {
  // Get a reference to the image in whatever way suits.
  let image = document.getElementById('image-id');

  // Update the source.
  img.src = src;

  // Wait for it to load.
  await new Promise((resolve) => { image.onload = resolve; });

  // Done!
  console.log('image loaded! do something...');
}

If you are using React.js, you could do this:

render() {

// ...

<img 
onLoad={() => this.onImgLoad({ item })}
onError={() => this.onImgLoad({ item })}

src={item.src} key={item.key}
ref={item.key} />

// ... }

Where:

  • - onLoad (...) now will called with something like this: { src: "https://......png", key:"1" } you can use this as "key" to know which images is loaded correctly and which not.
  • - onError(...) it is the same but for errors.
  • - the object "item" is something like this { key:"..", src:".."} you can use to store the images' URL and key in order to use in a list of images.


  • You could use the load()-event in jQuery but it won't always fire if the image is loaded from the browser cache. This plugin https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js can be used to remedy that problem.


    Here is jQuery equivalent:

    var $img = $('img');
    
    if ($img.length > 0 && !$img.get(0).complete) {
       $img.on('load', triggerAction);
    }
    
    function triggerAction() {
       alert('img has been loaded');
    }
    

    Not suitable for 2008 when the question was asked, but these days this works well for me:

    async function newImageSrc(src) {
      // Get a reference to the image in whatever way suits.
      let image = document.getElementById('image-id');
    
      // Update the source.
      img.src = src;
    
      // Wait for it to load.
      await new Promise((resolve) => { image.onload = resolve; });
    
      // Done!
      console.log('image loaded! do something...');
    }
    

    Image.onload() will often work.

    To use it, you'll need to be sure to bind the event handler before you set the src attribute.

    Related Links:

    Example Usage:

    _x000D_
    _x000D_
        window.onload = function () {_x000D_
    _x000D_
            var logo = document.getElementById('sologo');_x000D_
    _x000D_
            logo.onload = function () {_x000D_
                alert ("The image has loaded!");  _x000D_
            };_x000D_
    _x000D_
            setTimeout(function(){_x000D_
                logo.src = 'https://edmullen.net/test/rc.jpg';         _x000D_
            }, 5000);_x000D_
        };
    _x000D_
     <html>_x000D_
        <head>_x000D_
        <title>Image onload()</title>_x000D_
        </head>_x000D_
        <body>_x000D_
    _x000D_
        <img src="#" alt="This image is going to load" id="sologo"/>_x000D_
    _x000D_
        <script type="text/javascript">_x000D_
    _x000D_
        </script>_x000D_
        </body>_x000D_
        </html>
    _x000D_
    _x000D_
    _x000D_


    You can use the .complete property of the Javascript image class.

    I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:

    var gAllImages = [];
    
    function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
    {
        gAllImages = [];
    
        for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
        {
            var theImage = new Image();
            theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
            gAllImages.push(theImage);
    
            setTimeout('checkForAllImagesLoaded()', 5);
            window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
    
            // make a new div containing that image
            makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
        }
    }
    
    function checkForAllImagesLoaded()
    {
        for (var i = 0; i < gAllImages.length; i++) {
            if (!gAllImages[i].complete) {
                var percentage = i * 100.0 / (gAllImages.length);
                percentage = percentage.toFixed(0).toString() + ' %';
    
                userMessagesController.setMessage("loading... " + percentage);
                setTimeout('checkForAllImagesLoaded()', 20);
                return;
            }
        }
    
        userMessagesController.setMessage(globals.defaultTitle);
    }
    

    Here is jQuery equivalent:

    var $img = $('img');
    
    if ($img.length > 0 && !$img.get(0).complete) {
       $img.on('load', triggerAction);
    }
    
    function triggerAction() {
       alert('img has been loaded');
    }
    

    If the goal is to style the img after browser has rendered image, you should:

    const img = new Image();
    img.src = 'path/to/img.jpg';
    
    img.decode().then(() => {
    /* set styles */
    /* add img to DOM */ 
    });
    

    because the browser first loads the compressed version of image, then decodes it, finally paints it. since there is no event for paint you should run your logic after browser has decoded the img tag.


    Image.onload() will often work.

    To use it, you'll need to be sure to bind the event handler before you set the src attribute.

    Related Links:

    Example Usage:

    _x000D_
    _x000D_
        window.onload = function () {_x000D_
    _x000D_
            var logo = document.getElementById('sologo');_x000D_
    _x000D_
            logo.onload = function () {_x000D_
                alert ("The image has loaded!");  _x000D_
            };_x000D_
    _x000D_
            setTimeout(function(){_x000D_
                logo.src = 'https://edmullen.net/test/rc.jpg';         _x000D_
            }, 5000);_x000D_
        };
    _x000D_
     <html>_x000D_
        <head>_x000D_
        <title>Image onload()</title>_x000D_
        </head>_x000D_
        <body>_x000D_
    _x000D_
        <img src="#" alt="This image is going to load" id="sologo"/>_x000D_
    _x000D_
        <script type="text/javascript">_x000D_
    _x000D_
        </script>_x000D_
        </body>_x000D_
        </html>
    _x000D_
    _x000D_
    _x000D_


    If the goal is to style the img after browser has rendered image, you should:

    const img = new Image();
    img.src = 'path/to/img.jpg';
    
    img.decode().then(() => {
    /* set styles */
    /* add img to DOM */ 
    });
    

    because the browser first loads the compressed version of image, then decodes it, finally paints it. since there is no event for paint you should run your logic after browser has decoded the img tag.


    If you are using React.js, you could do this:

    render() {
    

    // ...

    <img 
    onLoad={() => this.onImgLoad({ item })}
    onError={() => this.onImgLoad({ item })}
    
    src={item.src} key={item.key}
    ref={item.key} />
    

    // ... }

    Where:

  • - onLoad (...) now will called with something like this: { src: "https://......png", key:"1" } you can use this as "key" to know which images is loaded correctly and which not.
  • - onError(...) it is the same but for errors.
  • - the object "item" is something like this { key:"..", src:".."} you can use to store the images' URL and key in order to use in a list of images.


  • You could use the load()-event in jQuery but it won't always fire if the image is loaded from the browser cache. This plugin https://github.com/peol/jquery.imgloaded/raw/master/ahpi.imgload.js can be used to remedy that problem.


    these functions will solve the problem, you need to implement the DrawThumbnails function and have a global variable to store the images. I love to get this to work with a class object that has the ThumbnailImageArray as a member variable, but am struggling!

    called as in addThumbnailImages(10);

    var ThumbnailImageArray = [];
    
    function addThumbnailImages(MaxNumberOfImages)
    {
        var imgs = [];
    
        for (var i=1; i<MaxNumberOfImages; i++)
        {
            imgs.push(i+".jpeg");
        }
    
        preloadimages(imgs).done(function (images){
                var c=0;
    
                for(var i=0; i<images.length; i++)
                {
                    if(images[i].width >0) 
                    {
                        if(c != i)
                            images[c] = images[i];
                        c++;
                    }
                }
    
                images.length = c;
    
                DrawThumbnails();
            });
    }
    
    
    
    function preloadimages(arr)
    {
        var loadedimages=0
        var postaction=function(){}
        var arr=(typeof arr!="object")? [arr] : arr
    
        function imageloadpost()
        {
            loadedimages++;
            if (loadedimages==arr.length)
            {
                postaction(ThumbnailImageArray); //call postaction and pass in newimages array as parameter
            }
        };
    
        for (var i=0; i<arr.length; i++)
        {
            ThumbnailImageArray[i]=new Image();
            ThumbnailImageArray[i].src=arr[i];
            ThumbnailImageArray[i].onload=function(){ imageloadpost();};
            ThumbnailImageArray[i].onerror=function(){ imageloadpost();};
        }
        //return blank object with done() method    
        //remember user defined callback functions to be called when images load
        return  { done:function(f){ postaction=f || postaction } };
    }
    

    You can use the .complete property of the Javascript image class.

    I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:

    var gAllImages = [];
    
    function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
    {
        gAllImages = [];
    
        for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
        {
            var theImage = new Image();
            theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
            gAllImages.push(theImage);
    
            setTimeout('checkForAllImagesLoaded()', 5);
            window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
    
            // make a new div containing that image
            makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
        }
    }
    
    function checkForAllImagesLoaded()
    {
        for (var i = 0; i < gAllImages.length; i++) {
            if (!gAllImages[i].complete) {
                var percentage = i * 100.0 / (gAllImages.length);
                percentage = percentage.toFixed(0).toString() + ' %';
    
                userMessagesController.setMessage("loading... " + percentage);
                setTimeout('checkForAllImagesLoaded()', 20);
                return;
            }
        }
    
        userMessagesController.setMessage(globals.defaultTitle);
    }
    

    .complete + callback

    This is a standards compliant method without extra dependencies, and waits no longer than necessary:

    var img = document.querySelector('img')
    
    function loaded() {
      alert('loaded')
    }
    
    if (img.complete) {
      loaded()
    } else {
      img.addEventListener('load', loaded)
      img.addEventListener('error', function() {
          alert('error')
      })
    }
    

    Source: http://www.html5rocks.com/en/tutorials/es6/promises/


    Life is too short for jquery.

    _x000D_
    _x000D_
    function waitForImageToLoad(imageElement){_x000D_
      return new Promise(resolve=>{imageElement.onload = resolve})_x000D_
    }_x000D_
    _x000D_
    var myImage = document.getElementById('myImage');_x000D_
    var newImageSrc = "https://pmchollywoodlife.files.wordpress.com/2011/12/justin-bieber-bio-photo1.jpg?w=620"_x000D_
    _x000D_
    myImage.src = newImageSrc;_x000D_
    waitForImageToLoad(myImage).then(()=>{_x000D_
      // Image have loaded._x000D_
      console.log('Loaded lol')_x000D_
    });
    _x000D_
    <img id="myImage" src="">
    _x000D_
    _x000D_
    _x000D_


    You can use the .complete property of the Javascript image class.

    I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:

    var gAllImages = [];
    
    function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
    {
        gAllImages = [];
    
        for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
        {
            var theImage = new Image();
            theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
            gAllImages.push(theImage);
    
            setTimeout('checkForAllImagesLoaded()', 5);
            window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
    
            // make a new div containing that image
            makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
        }
    }
    
    function checkForAllImagesLoaded()
    {
        for (var i = 0; i < gAllImages.length; i++) {
            if (!gAllImages[i].complete) {
                var percentage = i * 100.0 / (gAllImages.length);
                percentage = percentage.toFixed(0).toString() + ' %';
    
                userMessagesController.setMessage("loading... " + percentage);
                setTimeout('checkForAllImagesLoaded()', 20);
                return;
            }
        }
    
        userMessagesController.setMessage(globals.defaultTitle);
    }
    

    .complete + callback

    This is a standards compliant method without extra dependencies, and waits no longer than necessary:

    var img = document.querySelector('img')
    
    function loaded() {
      alert('loaded')
    }
    
    if (img.complete) {
      loaded()
    } else {
      img.addEventListener('load', loaded)
      img.addEventListener('error', function() {
          alert('error')
      })
    }
    

    Source: http://www.html5rocks.com/en/tutorials/es6/promises/


    You can use the .complete property of the Javascript image class.

    I have an application where I store a number of Image objects in an array, that will be dynamically added to the screen, and as they're loading I write updates to another div on the page. Here's a code snippet:

    var gAllImages = [];
    
    function makeThumbDivs(thumbnailsBegin, thumbnailsEnd)
    {
        gAllImages = [];
    
        for (var i = thumbnailsBegin; i < thumbnailsEnd; i++) 
        {
            var theImage = new Image();
            theImage.src = "thumbs/" + getFilename(globals.gAllPageGUIDs[i]);
            gAllImages.push(theImage);
    
            setTimeout('checkForAllImagesLoaded()', 5);
            window.status="Creating thumbnail "+(i+1)+" of " + thumbnailsEnd;
    
            // make a new div containing that image
            makeASingleThumbDiv(globals.gAllPageGUIDs[i]);
        }
    }
    
    function checkForAllImagesLoaded()
    {
        for (var i = 0; i < gAllImages.length; i++) {
            if (!gAllImages[i].complete) {
                var percentage = i * 100.0 / (gAllImages.length);
                percentage = percentage.toFixed(0).toString() + ' %';
    
                userMessagesController.setMessage("loading... " + percentage);
                setTimeout('checkForAllImagesLoaded()', 20);
                return;
            }
        }
    
        userMessagesController.setMessage(globals.defaultTitle);
    }
    

    Examples related to javascript

    need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

    Examples related to image

    Reading images in python Numpy Resize/Rescale Image Convert np.array of type float64 to type uint8 scaling values Extract a page from a pdf as a jpeg How do I stretch an image to fit the whole background (100% height x 100% width) in Flutter? Angular 4 img src is not found How to make a movie out of images in python Load local images in React.js How to install "ifconfig" command in my ubuntu docker image? How do I display local image in markdown?

    Examples related to callback

    When to use React setState callback How to send an HTTP request with a header parameter? javascript function wait until another function to finish What is the purpose of willSet and didSet in Swift? How to refactor Node.js code that uses fs.readFileSync() into using fs.readFile()? Aren't promises just callbacks? How do I convert an existing callback API to promises? How to access the correct `this` inside a callback? nodeJs callbacks simple example Callback after all asynchronous forEach callbacks are completed

    Examples related to loading

    JavaScript Loading Screen while page loads How to add a spinner icon to button when it's in the Loading state? Display a loading bar before the entire page is loaded WPF loading spinner Using the "animated circle" in an ImageView while loading stuff Display loading image while post with ajax Running sites on "localhost" is extremely slow open resource with relative path in Java Dynamic loading of images in WPF How to create a JavaScript callback for knowing when an image is loaded?