异步/等待vs那么哪个是最佳性能?

Fra*_*sco 2 javascript node.js async-await

我在JavaScript中有一个简单的代码,可以在API中执行请求并返回响应。但是在这种情况下,我将有成千上万的请求。因此,哪个代码选项会表现更好,为什么。另外,最近推荐哪一种作为好习惯?

第一种选择是使用.then来解决承诺,第二种选择是使用async / await。

在我的测试中,这两个选项的结果非常相似,没有显着差异,但是我不确定其范围。

// Using then
doSomething(payload) {
  const url = 'https://link-here/consultas';
  return this.axios.get(url, {
    params: {
      token: payload.token,
      chave: payload.chave,
    },
   }).then(resp => resp.data);
}

// Using Async / await
async doSomething(payload) {
   const url = 'https://link-here/consultas';
   const resp = await this.axios.get(url, {
   params: {
     token: payload.token,
     chave: payload.chave,
    },
 });
 return resp.data;
}
Run Code Online (Sandbox Code Playgroud)

任何解释都将具有重大价值。

use*_*209 55

这个线程应该有一些更正。await并且.then会给出非常不同的结果,并且应该出于不同的原因而使用。

await将等待某事,然后继续下一行。它也是两者中更简单的一个,因为它的机械行为更像同步行为。您执行第 1 步,等待,然后继续。

console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");
Run Code Online (Sandbox Code Playgroud)

.then从原始调用中分离出来并开始在其自己的范围内运行,并将在原始范围无法预测的时间进行更新。如果我们可以暂时把语义放在一边,它会“更加异步”,因为它离开了旧的范围并分支到一个新的范围。

console.log("Runs first.");
SomeFunction().then((value) => {console.log("Runs last (probably). Didn't use await on SomeFunction().")})
console.log("Runs second (probably).");
Run Code Online (Sandbox Code Playgroud)

  • 为什么await/.then会给出不同的结果。它们被设计为用不同的语法来做同样的事情。其次,“await”在技术上并不是阻塞行为,因为它不会阻塞线程。我不会将 `.then` 描述为“更加异步”。它们都是异步的,我认为这样思考没有帮助。 (12认同)
  • 我添加了一些清晰度来证明我的意思。这是两个截然不同的功能。显然,异步涉及更多讨论,这属于完整的指南,并且我明确地以“如果我们把语义放在一边”作为声明的开头。 (2认同)

Nux*_*Nux 38

作为对 @user280209 答案的更多解释,让我们考虑以下返回 Promise 的函数,并将其执行与.then()和进行比较async await

function call(timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`This call took ${timeout} seconds`);
      resolve(true);
    }, timeout * 1000);
  });
}
Run Code Online (Sandbox Code Playgroud)

.then()

(async () => {
  call(5).then((r) => {
    console.log(r);
  });
  await call(2); //This will print result first
  await call(1);
})();
Run Code Online (Sandbox Code Playgroud)

运行上述调用时,日志将是

This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,.then()在完成之前并没有暂停其下面一行的执行。

async/wait

This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true
Run Code Online (Sandbox Code Playgroud)

运行时上述函数日志将是

This call took 5 seconds
This call took 2 seconds
This call took 1 seconds
Run Code Online (Sandbox Code Playgroud)

所以我认为如果你的承诺结果不会在下面的行中使用,.then()可能会更好。

  • @jfriend00你的答案中的倒数第二段似乎暗示了await然后有相同的行为,它们唯一的区别是await的输入时间更短。This+user280209的回答澄清了事实并非如此,它们有明显的区别。确实,这与问题没有明确相关,但是如果人们想更好地理解等待与然后,添加此信息会提供隐含重要的信息。 (4认同)
  • 值得一提的是,“.then()”示例的挂起时间为 3 秒,而“async”示例的挂起时间为 8 秒。换句话说,每个“await”都会暂停线程并真正“等待”结果,而“.then()”则异步运行。 (4认同)
  • 谢谢你的例子!在第一个“call(5).then”上,当您等待“await call(2)”和“await call(1)”时,它会在后台继续执行吗? (2认同)

小智 9

对于那些说“await 会阻塞代码直到异步调用返回”的人来说,您没有抓住重点。“await”是promise.then() 的语法糖。它有效地将函数的其余部分包装在它为您创建的 Promise 的 then 块中。不存在真正的“阻塞”或“等待”。

run();

async function run() {
    console.log('running');
    makePromises();
    console.log('exiting right away!');
}

async function makePromises() {
    console.log('make promise 1');
    const myPromise = promiseMe(1)
    .then(msg => {
        console.log(`What i want to run after the promise is resolved ${msg}`)
    })
    console.log('make promise 2')
    const msg = await promiseMe(2);
    console.log(`What i want to run after the promise is resolved via await ${msg}`)
}   

function promiseMe(num: number): Promise<string> {
    return new Promise((resolve, reject) => {
        console.log(`promise`)
        resolve(`hello promise ${num}`);
    })
}
Run Code Online (Sandbox Code Playgroud)

makePromises 中的await 行不会阻止任何内容,输出为:

  • 跑步
  • 做出承诺1
  • 承诺
  • 做出承诺2
  • 承诺
  • 马上退出!
  • 承诺解决后我想运行什么你好承诺 1
  • 通过等待 hello 承诺 2 解决承诺后我想运行什么

  • 如果使用await 将函数的尾部放入.then 块中,它确实会导致不同的行为。 (3认同)

jfr*_*d00 8

await只是的内部版本.then()(基本上做同样的事情)。选择一个选项的原因实际上与性能无关,但与所需的编码样式或编码便利性有关。当然,解释器还有更多机会使用进行内部优化await,但这不太可能是您决定使用哪种方法。如果其他条件都一样,我将await出于上述原因进行选择。但是,我首先选择使代码更易于编写,理解,维护和测试的代码。

如果使用得当,await通常可以节省大量代码,从而使代码更易于阅读,测试和维护。这就是它被发明的原因。

这两个代码版本之间没有有意义的区别。当axios调用成功或发生错误时,两者均会达到相同的结果。

在哪里await可以让更多的便利不同的是,如果你有多个连续的异步调用了需要被序列化。然后,您无需使用括号将它们分别放在.then()处理程序中以正确地链接它们,而是可以使用await外观更简单的代码。

既一个常见的错误await,并.then()是忘记正确的错误处理。如果此函数中的错误处理愿望只是返回被拒绝的承诺,则两个版本都将执行相同的操作。但是,如果您连续有多个异步调用,并且想要做的事情比返回第一个拒绝还要复杂,那么and和/错误处理技术await.then().catch()将大不相同,并且看起来更简单的方法将取决于情况。

  • @Davos - 并不是真正的风格选择。通常不建议混合使用`await`和`.then()`,因为它只会使代码更难以理解和理解。一般来说,如果可以使用,“await”的代码将更容易编写和遵循。 (3认同)

小智 5

实际上。Await/Async 可以更有效地执行,因为 Promise.then() 会失去执行后调用它的范围,您将回调附加到回调堆栈。

其原因是:系统现在必须存储对调用 .then() 的位置的引用。如果发生错误,它必须正确指向错误发生的位置,否则,如果没有范围(因为系统在调用 Promise 后恢复执行,等待稍后返回 .then()),它就无法指向错误发生的地方。

Async/Await 暂停正在调用的方法的执行,从而保留引用。