Home > Blockchain >  Get a boolean value from async function and then validate an IF ELSE condition
Get a boolean value from async function and then validate an IF ELSE condition

Time:02-02

This is the code snippet. Here, I want to check if an image's width OR heigh exceeds 100, I want to return true so that I can restrict uploading such file/image to the array.

const getHeightWidth = async () => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    await reader.addEventListener('load', async (e) => {
        const image = new Image();
        image.src = reader.result;
        await image.addEventListener('load', function () {
            const { height, width } = this;
            invalidFileHeightWidth = !!((height !== 100 || width !== 100));
            return invalidFileHeightWidth;
        });
    });
};

I tried Promise.resolve as well as a direct return statement but no luck so far

CodePudding user response:

If you want to use async/await, you will want to wrap the events inside a Promise constructor.

Below is a simple working example, select a image file and it will give you the size.

function getFileSize(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = e => {
      const image = new Image();
      image.onload = e => resolve([image.width, image.height]);
      image.onerror = e => reject(e);
      image.src = reader.result;
    }
    reader.onerror = e => reject(e);
    reader.readAsDataURL(file);
  });
}


document.querySelector('input').addEventListener('change', async e => {
  const span = document.querySelectorAll('span');
  const size = await getFileSize(e.target.files[0]);
  span[0].innerText = size[0];
  span[1].innerText = size[1];
});
span {
  font-weight: bold;
}
<input type="file" accept="image/png, image/gif, image/jpeg"/>

<div>width: <span></span></div>
<div>height: <span></span></div>

CodePudding user response:

I would break this into five separate functions:

  1. loadImageFromFile ~ a Promise that loads by filename using a FileReader
  2. loadImage ~ a Promise that sets the src of an Image object
  3. loadImageFromFile ~ combines the two above functions into one call
  4. isValidSize ~ validates the width/height of a given image
  5. previewFile ~ an event handler for listening to a file input

const previewFile = async () => {
  const preview = document.querySelector('img');
  const file = document.querySelector('input[type=file]').files[0];
  const image = await loadImageFromFile(file);
  const isValid = isValidSize(image);
  console.log(`Image size valid: ${isValid }`);
  preview.src = image.src; // Update preview
};

const loadImageFromFile = async (file) => {
  const reader = await readFile(file);
  return loadImage(reader.result);
};

const readFile = async (file) =>
  new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.addEventListener('load', (e) => resolve(fileReader));
    fileReader.addEventListener('error', (e) => reject(e));
  });

const loadImage = async (imageData) =>
  new Promise((resolve, reject) => {
    const image = new Image();
    image.src = imageData;
    image.addEventListener('load', function (e) { resolve(this);  });
    image.addEventListener('error', function (e) { reject(e);  });
  });

const isValidSize = (image) => {
  const { height, width } = image;
  return width === 100 && height === 100;
};
<input type="file" onchange="previewFile()" /><br />
<img src="" height="100" alt="Image preview" />

If you want one giant monolithic function, you can try:

Note: You are using this to only check if the image is valid. You will need to load the image again, if you want to do more with the image. This is why the first example is a better choice. It separates validation from the loading.

const preview = document.querySelector('img');

const previewFile = async () => {
  const preview = document.querySelector('img');
  const file = document.querySelector('input[type=file]').files[0];
  const isValid = await isValidSize(file);
  console.log(`Image size valid: ${isValid }`);
};

const isValidSize = async (file, expectedWidth = 100, expectedHeight = 100) =>
  new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.readAsDataURL(file);
    fileReader.addEventListener('load', (e) => {
      const image = new Image();
      image.src = fileReader.result;
      image.addEventListener('load', function (e) {
        const { height, width } = this;
        resolve(width === expectedWidth && height === expectedHeight);
      });
      image.addEventListener('error', function (e) { reject(false);  });
      preview.src = image.src; // This is now coupled...
    });
    fileReader.addEventListener('error', (e) => reject(false));
  });
<input type="file" onchange="previewFile()" /><br />
<img src="" height="100" alt="Image preview" />

  • Related