1

I have a for loop for checking multiple uploaded image's aspect ratio, after completing the loop i want to check ratio in if else condition to redirect user. Problem is the conditions are checked before loop finishes, I need the loop to be completed before checking conditions. I found out async whilst might be suitable here but i'm confused about the best approach for implemetation, can anyone give me workaround to perform the code sequentially.

//check image ratio         
var validImageRatio = true;
for(i=0; i<req.files.propertyPhoto.length; i++){
    
    var tempFile = req.files.propertyPhoto[i].tempFilePath.replace(/\\/g, '/');
    var ratio;var width;var height;
    var acceptedRatio = 3;
    
    //get image ratio
    sizeOf(tempFile, function (err, dimensions) {
        width = dimensions.width;
        height = dimensions.height;
        ratio = width/height;
    });
    if (ratio < (acceptedRatio - 0.1) || ratio > (acceptedRatio + 0.1)) {
        validImageRatio = false;
        break;
    }
}
//if ratio invalid, redirect
if (!validImageRatio) {
    ...
}
//if ratio valid, upload
else{
    ...
}
RRR
  • 507
  • 4
  • 17
  • Does this answer your question? [Callback after all asynchronous forEach callbacks are completed](https://stackoverflow.com/questions/18983138/callback-after-all-asynchronous-foreach-callbacks-are-completed) – Matt Jul 07 '20 at 02:54
  • 1
    The `sizeOf` function runs asynchronously so node continues on before the `width`/`height`/`ratio` values are set. – Matt Jul 07 '20 at 02:56

2 Answers2

1

Since you're doing the check asynchronously, the synchronous code will run first. If you use async/await inside the for loop, it will block each iteration of the loop making it run slower. The approach you can go for is to use Promise.all to run the checks concurrently.

const promises = req.files.propertyPhoto.map(prop => new Promise(resolve => {
    const tempFile = prop.tempFilePath.replace(/\\/g, '/');
    const acceptedRatio = 3;

    // get image ratio
    sizeOf(tempFile, function (err, dimensions) {
        const width = dimensions.width;
        const height = dimensions.height;
        const ratio = width / height;
        if (ratio < (acceptedRatio - 0.1) || ratio > (acceptedRatio + 0.1)) {
            return resolve(false);
        }
        resolve(true);
    });
}));

const result = await Promise.all(promises);

if (result.some(r => r === false)) {
    // if any of the ratio is invalid, redirect

} else {
    // else upload
    
}
Duc Nguyen
  • 836
  • 6
  • 12
0

I'm guessing at what you mean, but a for-loop would complete before checking the conditions at the bottom except that you include a "break" statement. The break statement makes the for-loop stop executing and move on.

freqnseverity
  • 146
  • 1
  • 7