Search code examples
javascriptes6-promise

Wait for function to finish running before iterating


How can I wait for the image.onload function to finish running before iterating the next value in an array??

for (let i = 0; i < Object.keys(images_list_complex_form).length; i++) {
    for (let k = 0; k < images_list_complex_form[i].length; k++) {
        console.log('ITERATE');
        image.onload = function () {
            console.log('STARTED IMAGE ON LOAD');
        }
    }
}

I am receiving multiple 'iterates' before receiving started image on load

As sugguested by @amadan, i have tried adding in async and await into the for loop however, after doing so the image111.onload is never triggered anymore. I never get to see the console log "Started image on load"

        async function rectifyMissingSavedImages(images_list_complex_form_array,annotationIndexArray){
            console.log(images_list_complex_form_array);
            for(let i = 0; i < Object.keys(images_list_complex_form_array).length; i++){
                for(const[index2,value2] of Object.entries(images_list_complex_form_array[i])){
                    if (Object.keys(annotationIndexArray).length == 0 || (!annotationIndexArray[i] || annotationIndexArray[i].includes(String(k)) == false)) {
                        let image_url = URL.createObjectURL(value2);
                        let image111 = new Image();
                        let canvas = new fabric.Canvas();
                        
                        console.log(image111);
                        await new Promise((resolve,reject) =>{
                            image111.onload = evt => {
                                console.log("??");
                                console.log('STARTED IMAGE ON LOAD');
                                let background = new fabric.Image(image);
                                canvas.setHeight(background.height);
                                canvas.setWidth(background.width);
                                canvas.setBackgroundImage(background, canvas.renderAll.bind(canvas));
                                console.log("ABOUT TO RESOLVE");

                                image.src = image_url;
                                resolve();
                            }
                        });

Solution

  • The easiest way is to create and await a promise inside the loop. Something like:

    async function loadImages() {
      for (...) {
        await new Promise((resolve, reject) => {
          image.onload = evt => {
            console.log('STARTED IMAGE ON LOAD');
            resolve();
          }
          image.onerror = reject;
        });
      }
    }
    

    This is the only way that a loop can "pause" in JavaScript. Any other way involves either chaining promises, which is messy, or nesting callbacks, which is even worse.