I can't get the program execution to pause so that all files are loaded before moving to another function. Basically, in my program, path of all images are extracted. Then, it is resized and compressed. My issue is, program moves to compress before it finished resizing. Please take a look and recommend some solutions.
const path = require('path');
const fs = require('fs');
const jimp = require('jimp');
const compress_images = require('compress-images');
// gets the names of all the images in the folder
// accepts the name of the folder in arguments
function getImagesPath (directory) {
const directoryPath = path.join(__dirname, directory);
const images = fs.readdirSync(directoryPath);
images.forEach(function (image, i) {
images[i] = path.join(__dirname, directory, image);
})
return images;
}
// function to check if the image date and current date is same
function isSameDate(path, currentDate) {
const imgDate = fs.statSync(path).birthtime.toDateString();
if (imgDate === currentDate) {
return true;
} else {
return false;
}
}
// function to check if the image is less than limit
function checkSize(path) {
const limit = 300000 // 300kb in bytes
const imgSize = fs.statSync(path).size;
if (imgSize < limit) {
return false
} else {
return true
}
}
// resizes the images
// receives the name of the images and the save folder in arguments
async function resizeImages(images, saveFolder) {
const shrinkPercentage = 60;
const directoryPath = path.join(__dirname, saveFolder);
const currentDate = new Date(Date.now()).toDateString();
await images.forEach(async function (image) {
// // if dates don't match; current iteration is skipped
// if (isSameDate(image, currentDate) === false) {
// return;
// }
// if the image is smaller than the limit; current iteration is skipped
if (checkSize(image) === false) {
return;
}
// reading the image
const img = await jimp.read(image);
// setting the dimensions
let width = img.bitmap.width - (img.bitmap.width * shrinkPercentage/100);
let height = img.bitmap.height - (img.bitmap.height * shrinkPercentage/100);
// resizing the image
if (width < 732) {
width = 732;
await img.resize(width, jimp.AUTO); // Jimp.AUTO can be used for height or width (not for both) for automatic scaling
} else {
await img.resize(width, height);
}
// saving the resized image
const newImageName = path.parse(image).name `-${width}X${height}` path.parse(image).ext;
await img.write(`${directoryPath}/${newImageName}`);
})
}
// compresses the image
async function compressImages(inputFolder, outputFolder) {
compress_images(inputFolder, outputFolder, { compress_force: true, statistic: true, autoupdate: true }, false,
{ jpg: { engine: "mozjpeg", command: ["-quality", "60"] } },
{ png: { engine: "pngquant", command: ["--quality=20-50", "-o"] } },
{ svg: { engine: false} },
{ gif: { engine: false} },
function (error, completed, statistic) {
console.log("-------------");
console.log(error);
console.log(completed);
console.log(statistic);
console.log("-------------");
}
);
}
// main function
async function main() {
//resizes the images
let images = getImagesPath('original');
await resizeImages(images, 'resized');
// compress the images
await compressImages('resized/**/*.{jpg,JPG,jpeg,JPEG,png}', 'compressed/');
}
main();
CodePudding user response:
forEach
does not return anything, so await
does nothing on it. You can make an array of promises and use Promise.all
to await
them.
const promises = images.map(async () => {
// ...
return img.write(`${directoryPath}/${newImageName}`);
});
await Promise.all(promises);
Minimum example:
const fn = async () => {
const promises = [1, 2, 3].map(async(v) => {
// Simulates slow op
await new Promise((r) => setTimeout(r, v * 100));
return v * 10;
});
return Promise.all(promises);
}
(async() => {
const data = await fn();
console.log('fn done with ', data);
})();