Search code examples
javascriptnode.jspromisegulpresolve

Promise resolves but doesn't fire


I've created a script that loops through a bunch of folders and processes them each in to webpack bundles. This works great, except that I can't figure out why the Promise around the loop isn't resolving.

Some things I've tried:

  • If I put a console.log("hello world") just before resolve(), within the } else { ... }, it outputs the log.
  • If I move resolve() out of the } else { ... }, it resolves, but the rest of my gulp task doesn't continue (separate, but related, issue).

I would appreciate some help in figuring this out. Most relevant chunk of code is below, the rest of it's at the link below.

// process all the script folders
const process_script_folders = () => {
   return new Promise((resolve) => {
       const FOLDER = script_folders.shift();

       // lint all scripts, except for critical
       if (FOLDER !== "critical") {
           const linted = lint_scripts(js_directory, FOLDER + ".js", source_directory + "/" + FOLDER + "/**/*");
           merged_streams.add(linted);
       }

       process_scripts(js_directory, FOLDER + ".js", source_directory + "/" + FOLDER + "/**/*").then((processed) => {
           merged_streams.add(processed);

           if (script_folders.length > 0) {
               process_script_folders();
           } else {
               // @TODO figure out why this isn't resolving
               resolve();
           }
       });
   });
};

return process_script_folders().then(() => {
    // ... do stuff
    console.log("Testing"); // currently never output
});

https://github.com/JacobDB/new-site/blob/dfeeb3260ab1b314e7562ef313c181adf2ef7f9c/gulp-tasks/scripts.js#L86-L89


Solution

  • You are recursively calling your promise, but none of these promises will resolve aside from the last one because you have put your resolve inside of your resolve clause. I think if you put the resolve outside of else and keep the rest the same it should resolve after finishing the recursion.

    if (script_folders.length > 0) {
        process_script_folders();
    } 
    resolve();
    

    Could you try it like that?

    EDIT: @Bergi is right. Doing it like the following should have it working properly I think. First a trivial example of what I'm suggesting you do:

    let i = 0
    const example_processing = () => {
        return new Promise((resolve) => {
            i++
            setTimeout(resolve, 1000);
        }).then(() => {
            console.log(i);
            return i < 10 ? example_processing() : "done"
        });
    };
    example_processing().then(console.log);

    With regards to your code it would look more like this I guess:

    const process_script_folders = () => {
        return new Promise((resolve) => {
            const FOLDER = script_folders.shift();
    
            // lint all scripts, except for critical
            if (FOLDER !== "critical") {
                const linted = lint_scripts(js_directory, FOLDER + ".js", source_directory + "/" + FOLDER + "/**/*");
                merged_streams.add(linted);
            }
    
            process_scripts(js_directory, FOLDER + ".js", source_directory + "/" + FOLDER + "/**/*").then((processed) => {
                merged_streams.add(processed);
                resolve();
            });
        }).then(() => script_folder.length > 0 ? process_script_folders() : "done");
     };