Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute promise after all promises were resolved

I've written some code that iterates through a directory, picks all the jpg files, rename them, create thumbs folder and put them inside that folder. I have also coded a function that generates a chunk of html per image, and at the end of the forEach loop should write all the output into a file.

// Read the directory
fs.readdir(dir, function (err, files) {

// Return the error if something went wrong
if (err) {
    console.log("Something went wrong");
}

//Make thumbs dir
fs.mkdirSync(thumbsFolder);

// For every file in the list
files.forEach(function (file) {
    var extension = path.extname(file);

    if (extension === ".jpg") {

        //Rename images
        var renameTask = renameImages(file, newFileName, extension);

        //Generating thumbs
        renameTask.then(function (newFileName) {
            generateThumbs(dir, newFileName, thumbsFolder)
            console.log("Promise resolved! Generating thumb for: " + newFileName);
            galleryHtml += generateThumbsGallery(newFileName, articleTitle);

        }, function (err) {
            console.log(err);
        });

    }

});

//Gallery output
console.log("Gallery Output: ");
console.log(galleryHtml);

});

My problem is that as logic as it sounds, galleryHtml (that is already defined in the upper part of the code, and not included here), returns undefined, because it runs before all the previous promises were resolved.

I've read about Promise.all method, and that I should pass a promises array, the question is that I don´t know how many promises would be returned, and in my code "renameTask" is the variable that acts as the promise receiver.

So, I would need some help -That I really appreciate in advance- to understand how to put the forEach as a promise itself, and after all forEach promises were resolved, then execute a final promise.

Thanks so much in advance.

UPDATE:

Felix, thanks so much, I'm closer now

// Read the directory
fs.readdir(dir, function (err, files) {

    // Return the error if something went wrong
    if (err) {
        console.log("Something went wrong");
    }

    var promises = [];

    //Make thumbs dir
    fs.mkdirSync(thumbsFolder);

    // For every file in the list
    files.forEach(function (file) {
        var extension = path.extname(file);

        if (extension === ".jpg") {

            //Rename images
            var renameTask = renameImages(file, newFileName, extension);


            promises.push(renameTask.then(function (newFileName) {
                    generateThumbs(dir, newFileName, thumbsFolder)
                    console.log("Promise resolved! Generating thumb for: " + newFileName);
                    galleryHtml += generateThumbsGallery(newFileName, articleTitle);
                }, function (err) {
                    console.log(err);
                }) 
            );

            console.log("<<<< Promises length: " + promises.length + " >>>>");

        }

    });

    Promise.all(promises).then(function () {
        console.log("<<<<< All promises were resolved >>>>");
    });

});

The thing is that I'm never getting the message "<<<<< All promises were resolved >>>>", I know that it should be a little thing that I'm missing.. Thanks again for your help!

like image 921
Guillermo Avatar asked Dec 24 '22 13:12

Guillermo


1 Answers

I've read about Promise.all method, and that I should pass a promises array, the question is that I don´t know how many promises would be returned, and in my code "renameTask" is the variable that acts as the promise receiver.

It's not as complicated as you seem to think. Create an array, add the promises to it and pass the array to Promise.all:

var promises = []; // array of promises

files.forEach(function (file) {
    var extension = path.extname(file);
    if (extension === ".jpg") {
        var renameTask = renameImages(file, newFileName, extension);
        promises.push(renameTask.then(...)); // add promise
    }

});

Promise.all(promises).then(...); // use array
like image 138
Felix Kling Avatar answered Dec 27 '22 03:12

Felix Kling