skip to Main Content

I’m trying to read the image dimensions in JS, but I face strange behaviours that I don’t understand. I have 3 Log-Console, and the one that I read the image properties is always executed after the contents are loaded (this is supposed to get executed the first), so practically I take always 0,0 of the dimensions in the first run.

var data_indexed = createDataSource(data_array);
console.log("third console - ", data_indexed)
function createDataSource(arr){
          var data = [];
          for (var j=1;j<arr.length;j++){
            //start to value 1 to ignore the id
            if (arr[j].search("static")==0){
              var getDimensions = async (url) => {
                const img = new Image();
                img.src = url;
                await img.decode();  
                return img;
              };
              var imgWidth1=0;
              var imgHeight1=0;
              getDimensions(arr[j]).then(img => {
                imgHeight1 = img.naturalHeight
                imgWidth1 = img.naturalWidth

                console.log("first console - ",imgHeight1,imgWidth1);
              });
              console.log("second console - ",imgHeight1,imgWidth1);
              
              data.push(
                {
                  src: `${arr[j]}`,
                  width: imgWidth1,
                  height: imgHeight1,
                  alt: `image ${j}`,
                },)
            }
            else if (arr[j].search("https://")==0){
              var res = arr[j].split("=");
              var vidEmbed = "https://www.youtube.com/embed/"+res[1];
              data.push(
                {
                  html: `<div class="ratio ratio-16x9 "><iframe src="${vidEmbed}" allowfullscreen></iframe></div>`
                },
              )
            }

          } 
          return data;
        }

Here is the result:
enter image description here

2

Answers


  1. I have tried your code and get message on console like this

    second console – 0 0

    first console – 48 48

    var getDimensions = async (url) => {
            const img = new Image();
            img.src = url;
            await img.decode();
            return img;
          };
          var imgWidth1 = 0;
          var imgHeight1 = 0;
          getDimensions("./image.png").then((img) => {
            imgHeight1 = img.naturalHeight;
            imgWidth1 = img.naturalWidth;
    
            console.log("first console - ", imgHeight1, imgWidth1);
          });
          console.log("second console - ", imgHeight1, imgWidth1);
    

    I’ve changed the code like this.

      (async () => {
        var getDimensions = async (url) => {
          const img = new Image();
          img.src = url;
          await img.decode();
          return img;
        };
        var imgWidth1 = 0;
        var imgHeight1 = 0;
        var img = await getDimensions("./image.png");
        imgHeight1 = img.naturalHeight;
        imgWidth1 = img.naturalWidth;
        console.log("first console - ", imgHeight1, imgWidth1);
        console.log("second console - ", imgHeight1, imgWidth1);
      })();
    

    The main reason which makes you confusion is that async function and await.
    As you’ve mentioned we could get image dimension after image is loaded.

    console.log("second console – ",imgHeight1,imgWidth1);

    This is called first than the code in then clause of getDimension() function since getDimension() is async function.
    we could get image dimensions after calling await on getDimension() function.

    Hope this would be helped!

    Login or Signup to reply.
  2. The problem you are facing is that instead of waiting for the image to load, you continue to the second console.log, and .then executes afterwards. To fix this, you need to make your top level function async, so async function createDataSource(url) and then await the function, which will cause your code first to wait for the image to get loaded and decoded.

    let img = await getDimensions(arr[j])
    let imgHeight1 = img.naturalHeight;
    let imgWidth1 = img.naturalWidth;
    
    console.log("first console - ",imgHeight1,imgWidth1);
    

    This will now trigger the variable assignments and console.log only after the getDimensions function is finished running.

    await-ing a function is preferrable to using .then, since it makes the code much cleaner.

    And for the third console to run third, you need to await the createDataSource call too: you need to wrap the call and console log in an async function like so:

    (async()=>{
        var data_indexed = await createDataSource(data_array);
        console.log("third console - ", data_indexed)
    })()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search