Async / await vs then 哪个最适合性能?

Posted

技术标签:

【中文标题】Async / await vs then 哪个最适合性能?【英文标题】:Async / await vs then which is the best for performance? 【发布时间】:2019-06-26 23:42:14 【问题描述】:

我在 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;

任何解释都会很有价值。

【问题讨论】:

您好!看看blog.pusher.com/promises-async-await。并且不要忘记用 try/catch 块包装你的 async/await 代码。 性能差异不应该是真正值得烦恼的事情:无论如何,http 请求肯定会占用 >99% 的执行时间。如果您可以并行启动几个请求,并通过Promise.all 加入他们的响应,则可以获得真正的收益。然后启动下一批,...等等。 我不确定这是否可以在这里应用,但请参阅来自 V8 开发人员的一般建议 at the end of this article:“赞成 async 函数和 await 而不是手写的承诺代码”。 @NikolayVetrov - 没有理由将await 包装在try/catch 中。 OP 只想返回被拒绝的承诺,async 函数将捕获拒绝并自动执行此操作。在比这更复杂的错误处理情况下,try/catch 将是必需的和有用的。 【参考方案1】:

await 只是.then() 的内部版本(基本上做同样的事情)。选择其中一个的原因实际上与性能无关,而是与所需的编码风格或编码方便性有关。当然,解释器内部有a few more opportunities to optimize things 和await,但这不太可能是您决定使用哪个的方式。如果其他条件相同,我会选择await,原因如上所述。但是,我会首先选择哪个使代码更易于编写、理解、维护和测试。

使用得当,await 经常可以save you a bunch of lines of code making your code simpler to read, test and maintain。这就是它被发明的原因。

您的代码的两个版本之间没有有意义的区别。当 axios 调用成功或出错时,两者都达到相同的结果。

如果您有多个需要序列化的连续异步调用,await 可以带来更多便利的不同之处。然后,与其将它们分别放在 .then() 处理程序中以正确链接它们,不如使用 await 并拥有更简单的代码。

await.then() 的一个常见错误是忘记正确的错误处理。如果您在此函数中的错误处理愿望只是返回被拒绝的承诺,那么您的两个版本都会这样做。但是,如果您连续有多个异步调用,并且您想要执行比仅返回第一个拒绝更复杂的操作,那么 error handling techniques for await and .then()/.catch() 就完全不同了,这似乎更简单取决于具体情况。

【讨论】:

对。使用'await'的另一个好处是功能明确标记【参考方案2】:

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

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

console.log("Runs first.");
await SomeFunction();
console.log("Runs last.");

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

console.log("Runs first.");
SomeFunction().then((value) => console.log("Runs last (probably). Didn't use await on SomeFunction()."))
console.log("Runs second (probably).");

【讨论】:

为什么 await/.then 会给出不同的结果。它们旨在使用不同的语法来做同样的事情。其次,await 在技术上并不是阻塞行为,因为它不会阻塞线程。而且我不会将.then 描述为“更异步”。它们都是异步的,我认为这样考虑没有帮助。 请在您的回答中提供更多详细信息。正如目前所写的那样,很难理解您的解决方案。 我添加了一些清晰度来说明我的意思。这是两个非常不同的功能。显然更多的讨论涉及到异步,它属于完整指南,我清楚地在声明前加上“如果我们把语义放在一边。”【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

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

function call(timeout) 
  return new Promise((resolve, reject) => 
    setTimeout(() => 
      console.log(`This call took $timeout seconds`);
      resolve(true);
    , timeout * 1000);
  );

.then()

(async () => 
  call(5).then((r) => 
    console.log(r);
  );
  await call(2); //This will print result first
  await call(1);
)();

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

This call took 2 seconds
This call took 1 seconds
This call took 5 seconds
true

正如我们所见,.then() 在完成之前不会暂停其下一行的执行。

async/wait

(async () => 
  await call(5); //This will print result first
  await call(2); 
  await call(1);
)();

当运行上述函数日志将是

This call took 5 seconds
This call took 2 seconds
This call took 1 seconds

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

【讨论】:

感谢您提供的示例!在第一个call(5).then 上,它会在您等待await call(2)await call(1) 时在后台继续执行吗?【参考方案5】:

对于那些说 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`);
    )

makePromises 中的 await 行没有阻塞任何东西,输出为:

正在运行 承诺 1 承诺 承诺 2 承诺 马上退出! promise 解决后我要运行的内容 hello promise 1 通过 await hello promise 2 解决 promise 后我想要运行的内容

【讨论】:

以上是关于Async / await vs then 哪个最适合性能?的主要内容,如果未能解决你的问题,请参考以下文章

async/await 在名为“then”的类方法中

一起使用 async await 和 .then

在 async/await 之后使用 .then 是一种好方法吗?

async await promise

Flutter/Dart 中的 Future<void>, async, await, then, catchError

promise/async/await