javascript - 返回未决的 promise 有实际好处吗?

标签 javascript node.js asynchronous async-await

在很大程度上,我认为我了解异步函数在 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) 返回由较小函数给出的包装 promise ,稍后将解析为 void .

我对它的工作原理缺乏了解。在选项 1 中,执行是否在 subtask() 之前暂停。返回?这实际上意味着什么?这是否意味着异步 subtask同步执行?这是否意味着app ,调用run() ,也会暂停执行吗?如果 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
}

最佳答案

Promise 冒泡总是更好。这避免了创建一个额外的 Promise 对象,该对象也将被等待(不过,无论您使用哪种 JavaScript 引擎,这是否在幕后进行优化都值得争论)。

async function run() {
    await subtask();
    return; 
}

这会创建一个额外的Promise(以及随后将在链中执行的额外回调)。

async function run() {
    return subtask(); 
}

这实际上并没有按照您的想法进行。这还创建了一个额外的 Promise(因为您使用了 async 关键字),并且在功能上几乎与前面的示例相同。通过使用 async 关键字,您将创建并返回一个新的 Promise,它将解析/拒绝与创建的 Promise 相同的值对subtask()的调用。如果删除 async 关键字,那么这将避免创建额外不必要的 Promise

现在有了您的 Promise.all() 示例,我认为它们都是最佳的(假设您从第二个示例中删除了不必要的 async 关键字,如上所述)。第一个将创建 2 个 Promise(Promise.all() 一个,以及从 async 函数返回创建的一个),并且第二个也是如此(Promise.all() 一个,以及通过调用 then() 创建的一个)。无论你想使用哪个基本上取决于个人选择。就我个人而言,我喜欢第二个示例,因为它没有混合使用 async 函数和 Promise,我认为这更容易理解。

对于问题的最后一部分,只要存在 await 关键字(因此在 run() 调用中),执行就会暂停。

您还可以从本质上考虑使用 await 关键字来转换您的代码:

// Do some stuff
let result = await run();
// Do some other stuff

对此:

// Do some stuff
run().then(result => {
    // Do some other stuff
};

(await 的全部目的是减少嵌套引起的困惑/复杂性)

关于javascript - 返回未决的 promise 有实际好处吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52634031/

相关文章:

javascript - 将多个系列加载到图表中

javascript - phonegap 插件在 CLI 中显示错误

javascript - 可以使用 Node.js 中的传递/帮助函数调用异步生成器吗?

javascript - NodeJS : how to separate large strings into an array of numbers, 然后添加所有具有偶数索引的

javascript - JavaScript 中的异步原语是什么?

javascript - 任何人都可以提供一个 angularjs 设置的示例,该示例轮询数据并在收到数据时更新 UI 吗?

javascript - 不明白为什么布局不正确

c# - 使用 twilio 从 asp.net 异步发送短信

javascript - 我无法在 ExpressJS 中使用静态 JS 文件

android - PageAsyncTask endHandler 更新调用页面