【问题标题】:Promise resolves but doesn't firePromise 解决但没有触发
【发布时间】:2019-02-18 11:30:41
【问题描述】:

我创建了一个脚本,它遍历一堆文件夹并将它们分别处理到 webpack 包中。这很好用,只是我不知道为什么循环周围的Promise 没有解决。

我尝试过的一些事情:

  • 如果我在resolve() 之前放置一个console.log("hello world"),在} else { ... } 中,它会输出日志。
  • 如果我将 resolve() 移出 } else { ... },它会解决,但我的 gulp 任务的其余部分不会继续(单独但相关的问题)。

如果您能帮我解决这个问题,我将不胜感激。最相关的代码块在下面,其余的在下面的链接中。

// 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

【问题讨论】:

  • 你需要return resolve();吗?
  • 您的递归调用 process_script_folders() 无法解析外部调用返回的承诺
  • @bergi 我想我明白你的意思,但我不太确定如何处理它。承诺对我来说仍然是新的;你能举个例子来说明如何实现吗?
  • 您递归地调用 process_script_folders() 方法并在另一个 Promise 中解析该 Promise。 resolve() 不会被调用,因为你没有 resolve() 你的第一个承诺,所以 then 方法不会被第一个执行,因为你的 resolve 方法也不会被调用。

标签: javascript node.js promise gulp resolve


【解决方案1】:

您正在递归调用您的 Promise,但是除了最后一个 Promise 之外,这些 Promise 都不会解决,因为您已将您的 resolve 放入您的 resolve 子句中。我认为如果您将解析放在 else 之外并保持其余部分相同,则它应该在完成递归后解析。

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

你可以这样试试吗?

编辑:@Bergi 是对的。我认为这样做应该可以正常工作。首先是我建议你做的一个简单的例子:

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);

关于你的代码,我猜它看起来更像这样:

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");
 };

【讨论】:

  • 不,如果解决之前完成最里面的递归调用
  • @Bergi 你是对的。请检查我修改后的答案。
  • setTimeout 调用process_script_folders 不会有任何好处,但最后的sn-p 是完美的!
  • @Bergi 我举这个例子只是为了模拟一些处理的发生。我意识到拥有相同的函数名称有点令人困惑,我现在正在编辑它。这只是为了说明。最后一段代码是我实际提出的解决方案。
  • 啊,我明白了。仍然setTimeout 应该严格在new Promise 内:-) 我已经将它转换为可运行的sn-p
【解决方案2】:

我认为问题与您进行递归调用的方式有关。

尝试一下

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

【讨论】:

  • 这就是想法,但这是Promise constructor antipattern :-/
  • 如果他不想这样做,那么我认为唯一的选择是迭代而不是递归。递归调用完成后,您还能如何解决?
  • 不,递归就好了。但是要正确地做到这一点,你可以resolve(process_script_folders()),或者甚至更好地将resolve 作为回调传递给process_scripts,然后在then 回调中执行其他所有操作,你可以从中return process_script_folders();
猜你喜欢
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
  • 2017-10-08
  • 2019-02-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-18
  • 1970-01-01
相关资源
最近更新 更多