【发布时间】:2019-03-09 02:19:26
【问题描述】:
在很大程度上,我想我了解异步函数在 JavaScript / Node.js 中是如何工作的,并且我熟悉 async/await 的语法。但这个问题是关于一个非常具体的案例,我似乎在任何地方都找不到,而且我认为它涉及await的内部运作,这超出了我的理解。
首先,我将从一个简单的示例开始,然后将其扩展为真正的工作代码。 (注意:我实际上使用的是 Typescript,所以你会看到 void 而不是 undefined,但这对问题并不重要。)
async function subtask() {
// doSomeStuff();
return; // returns a `Promise<void>`
}
// async function run() {
// see options below
// }
function app() {
run().catch((e) => console.error(e));
}
选项 1
async function run() {
await subtask(); // resolves to `void`
return; // returns a new `Promise<void>`
}
选项 2
async function run() {
return subtask(); // returns a new Promise, resolving to the `Promise<void>` of `subtask()`
}
在上面的简单示例中,我有一个异步函数run,它调用了一个较小的异步函数subtask。这两个函数都必须返回一个Promise<void>。我有两个选择:(1)等待较小的函数并返回一个新的Promise<void>,或者(2)返回一个由较小的函数给出的包装承诺,稍后将解析为void。
我对它的工作原理缺乏了解。在选项 1 中,是否在 subtask() 返回之前暂停执行?这实际上是什么意思?这是否意味着异步subtask 同步执行?这是否意味着调用run() 的app 也会暂停执行?如果app 是异步的,会有什么不同吗?
让 Promise 冒泡并稍后解决,还是直接在 run 函数中解决它是“更好”(性能更高)吗?
这很重要的原因是,在我的实际代码中,我有一堆较小的子任务,它们都返回 void,然后大函数也必须返回 void——它不能返回数组。 (请注意,子任务不需要以任何特定顺序运行。)
选项 1
async function run() {
await Promise.all([
subtask0(),
subtask1(),
subtask2(),
]);
return;
}
选项 2
async function run() {
return Promise.all([
subtask0(),
subtask1(),
subtask2(),
]).then((_all) => {});
}
function app() {
// do some stuff
run(); // if `run` contains `await`, does execution pause here?
// what if `app` was async?
// do some more stuff
}
【问题讨论】:
-
选项 2 不需要使用异步,因为它已经返回了一个承诺
-
@Igor - 我的理解是用
async声明的函数将返回一个承诺。如果我需要一个函数来返回一个承诺,为什么我不能在上面声明async?不管是不是awaiting 什么? -
你在那里所做的(通过添加 async 而不是调用 await)正在向调用者返回一个包装在一个 Promise 中的 Promise。
-
关于性能,取决于您为此构建的环境,可能会被打字稿填充到一些生成器怪物中。检查打字稿游乐场上的实际结果代码以查看差异。我认为在功能上它们都非常相似,尽管 async 在返回的 Promise 中捕获异常。
标签: javascript node.js asynchronous async-await