skip to Main Content

I have a code that checks the ratio of images. It works 9 out of 10 times or even more but once in a while it doesn’t work because img.naturalWidth and img.naturalHeight returns 0. I can understand that the image is not loaded at that moment when I am trying to fetch the height and width of image but I am clueless why it happens rarely. The code is also inside reader.onload which is the solution I found in most of the online articles.

isValidFileRatio(selectedFile: Blob, width: number, height: number): any {
return new Promise((resolve, reject) => {
  const reader = new FileReader();

  const img = new Image();
  img.src = window.URL.createObjectURL(selectedFile);

  reader.readAsDataURL(selectedFile);
  reader.onload = () => {
    const ratio = img.naturalWidth / img.naturalHeight;
    
    resolve(ratio >= 1 && ratio <= 2);
  };
  reader.onerror = (error) => reject(error);
});

}

Any solution or suggestion appreciated. Thanks

2

Answers


  1. I think new FileReader() is useless and it has caused this bug. Change your code like this:

    isValidFileRatio(selectedFile: Blob, width: number, height: number): any {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.src = window.URL.createObjectURL(selectedFile);
            
            img.onload = () => {
                const ratio = img.naturalWidth / img.naturalHeight;
    
                resolve(ratio >= 1 && ratio <= 2);
            };
            img.onerror = (error) => reject(error);
        });
    
    Login or Signup to reply.
  2. The problem is that you are using filereader.onload instead of image.onload

    Here is how i would have solved it:

    I would have used createImageBitmap, instead of using FileReader, Image, or Canvas that would require a mix of callbacks and promises.

    I also tend to break out of promise chain when possible by making most of my own code sync. that way my own function dose not become async b/c something else is async.

    /**
     * @param {{ width: number, height: number }} image
     */
    function isValidFileRatio (image) {
      const ratio = image.width / image.height
      return ratio >= 1 && ratio <= 2
    }
    
    // Just to get a simple dummy image/png blob for demo
    var blob = new OffscreenCanvas(300, 200).getContext('2d').canvas.convertToBlob()
    
    blob
      .then(createImageBitmap)
      .then(isValidFileRatio)
      .then(console.log)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search