【问题标题】:Why is this loop in a then callback faster than in an async function?为什么 then 回调中的这个循环比异步函数中的更快?
【发布时间】:2021-08-11 17:44:33
【问题描述】:

当我出于学习目的而使用 TS 时,我发现 then 回调比使用 await 的异步函数花费更少。这是我的代码 sn-ps:

带有异步/等待的代码:

const asyncCodeBlocker = async function(){
    console.log("notAsync")
    await Promise.resolve();
    console.time("async");
    let i = 0;
    while (i < 1000000000) { i++; }
    console.timeEnd("async");
    return 'billion loops done with async';
}

asyncCodeBlocker().then(v => {console.log(v)})

console.log("mainStack")

结果:

notAsync
mainStack
async: 2.464s
billion loops done with async

带有嵌套承诺的代码:

const promiseCodeBlocker = function(){
    console.log("notAsyncInPromise")
    return Promise.resolve().then(() => {
        console.time("promise");
        let i = 0;
        while (i < 1000000000) { i++; }
        console.timeEnd("promise");
        return 'billion loops done with nested promise';
    })
}

promiseCodeBlocker().then(v => {console.log(v)})

console.log("mainStack")

结果:

notAsyncInPromise
mainStack
promise: 497.627ms
billion loops done with nested promise

为什么会这样?

【问题讨论】:

  • console.time 和console.timeEnd 之间的代码没有区别,因此您在执行测试之前使用async 或then 对测量时间没有影响。为每个“演示”运行多次,平均得到相同的时间
  • 这可能是不同功能类型的引擎实现(和优化)略有不同的产物,例如存储let i 的范围。但像往常一样,this microbenchmark is mostly meaningless for actual code.
  • 我使用 Node v14.17.0 运行此代码。我尝试的另一件事是直接在浏览器控制台中运行生成的 JS,这一次两种方式的结果都是一样的
  • @agalbenus 这表明更现代的 v8 版本可以更好地优化异步功能。尝试使用具有更新的 v8 引擎的节点版本 - v14.17 仍在 6.14.13 上,而节点 16.2 已经发布了 7.13.0。

标签: javascript typescript asynchronous async-await promise


【解决方案1】:

原始代码是用 TypeScript 编写的,但在社区成员用 JS 发布问题后被编辑和覆盖,以便能够运行 sn-ps。

事实证明,该行为是由我的 TS 配置引起的。我将 compiler 选项 "target" 设置为 es5。将其值更改为 es6 后,我设法为两个 sn-ps 获得了相同的结果。

原始代码及结果:

带有异步/等待的代码:

const asyncCodeBlocker: () => Promise<any> = async function(){
    console.log("notAsync")
    await Promise.resolve();
    console.time("async");
    let i = 0;
    while (i < 1000000000) { i++; }
    console.timeEnd("async");
    return 'billion loops done with async';
}

asyncCodeBlocker().then(v => {console.log(v)})

console.log("mainStack")

结果:

notAsync
mainStack
async: 2.464s
billion loops done with async

带有嵌套承诺的代码:

const promiseCodeBlocker: () => Promise<any> = function(){
    console.log("notAsyncInPromise")
    return Promise.resolve().then(() => {
        console.time("promise");
        let i = 0;
        while (i < 1000000000) { i++; }
        console.timeEnd("promise");
        return 'billion loops done with nested promise';
    })
}

promiseCodeBlocker().then(v => {console.log(v)})

console.log("mainStack")

结果:

notAsyncInPromise
mainStack
promise: 497.627ms
billion loops done with nested promise

【讨论】:

    猜你喜欢
    • 2021-10-16
    • 2014-11-26
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多