【发布时间】:2018-09-20 07:13:22
【问题描述】:
我有一个 gulp 任务,它从 GitHub 下载一些 JSON 文件,然后提示用户输入要在这些文件中替换的值。例如,我有一个 .ftpconfig 可以下载,然后要求用户输入主机名、用户名、密码和路径。
因为文件需要先下载后才能配置,而且每个文件都需要按顺序配置,所以我使用了相当多的嵌套回调。我想更改这个“回调地狱”系统,以便它使用 async/await 和/或 Promise,但我很难准确理解我的代码为什么不起作用;似乎承诺会异步触发他们的 .then() 函数,这对我来说没有意义。
我的目标如下:
- 异步下载所有配置文件
- 等待所有配置文件完成下载
- 从配置文件中读取现有设置
- 同步提示用户更改每个配置文件中的设置
我尝试了很多方法,但都没有奏效。我放弃了我使用过的代码,但这里是我尝试过的东西的粗略再现:
尝试 #1:
return new Promise((resolve) => {
// download files...
}).then((resolve) => {
// configure first file...
}).then((resolve) => {
// configure second file...
}).then((resolve) => {
// configure thrid file...
});
尝试 #2:
const CONFIG_FILES = async () => {
const bs_download = await generate_config("browsersync");
const ftp_download = await generate_config("ftp");
const rsync_download = await generate_config("rsync");
return new Promise(() => {
configure_json("browsersync");
}).then(() => {
configure_json("ftp");
}).then(() => {
configure_json("rsync");
});
};
我确信我做的事情很明显是错误的,但我对 JavaScript 的适应能力还不够,无法看到问题所在。任何帮助将不胜感激。
我的 gulp 任务可以在这里找到:
【问题讨论】:
-
如果其中的异步任务异步解决了 Promise,则 Promise 将按顺序运行。仅当您从 .then 返回一个承诺时,尝试 #1 才会起作用。尝试 #2 将不起作用,因为您从未解决过第一个承诺,然后您没有从任何 .then 中返回承诺。你不能让异步代码同步运行,但是你可以使用 Promise 让它顺序运行。 async/await 使它看起来是同步的,但实际上它仍然是一个 Promise 链,所以你应该首先让它与 Promise 一起工作,因为这是 async/await 的先决条件。
-
Promise 不仅仅神奇地使异步任务按顺序或同步运行。如果异步任务返回一个 Promise,它们可以在 .then 链中使用以使它们按顺序运行,否则您必须将它包装在一个 Promise 或另一个返回 Promise 的函数中,以在没有“回调地狱”的情况下具有相同的效果"。
-
谢谢,我认为这有助于我了解正在发生的事情。我会再试一次并报告。
-
我对该代码的主要建议是确保在出现错误时拒绝,您不希望有挥之不去的未解决的承诺。
-
line 234 可以缩写为
return configure_json(".rsyncconfig", "rsync", prompts)。无需围绕已经返回一个的东西创建一个承诺(在整个代码中重复几次)
标签: node.js asynchronous promise gulp