我们应该选择异步等待Javascript中的Promise

Vik*_*sal 10 javascript asynchronous v8 node.js async-await

我知道这async awaitPromise镇上的新东西,它是编写异步代码的新方法,我也知道

我们没有写.then,创建一个匿名函数来处理响应

Async/await 最终可以使用相同的构造,旧的try/catch来处理同步和异步错误

promise链返回的错误堆栈没有提供错误发生位置的线索.但是,async/await中的错误堆栈指向包含错误的函数

等等...

但在这里我做了一个简单的基准测试https://repl.it/repls/FormalAbandonedChimpanzee

在基准测试中,我已经运行了2次循环100万次.在第一个循环中,我调用的函数在另一个函数中返回1我正在调用一个函数,它抛出1作为异常.

调用返回1的函数的第一个循环所花费的时间几乎是将1作为错误抛出的函数的一半.

这表明所花费的时间throw几乎是所用时间的两倍return

node v7.4 linux/amd64

return takes 1.233seconds
1000000
throw takes 2.128seconds
1000000
Run Code Online (Sandbox Code Playgroud)

以下基准代码

function f1() {
  return 1;
}

function f2() {
  throw 1;
}

function parseHrtimeToSeconds(hrtime) {
    var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3);
    return seconds;
}

var sum = 0;
var start = 0;
var i = 0;

start = process.hrtime();
for (i = 0; i < 1e6; i++) {
  try {
    sum += f1();
  } catch (e) {
    sum += e;
  }
}
var seconds = parseHrtimeToSeconds(process.hrtime(start));
console.log('return takes ' + seconds + 'seconds');
console.log(sum);




sum = 0;
start = process.hrtime();
for (i = 0; i < 1e6; i++) {
  try {
    sum += f2();
  } catch (e) {
    sum += e;
  }
}

seconds = parseHrtimeToSeconds(process.hrtime(start));
console.log('throw takes ' + seconds + 'seconds');
console.log(sum);
Run Code Online (Sandbox Code Playgroud)

Der*_*會功夫 12

您的基准与async/awaitvs raw promises 之间的性能无关.我只能看到抛出一个错误需要更长的时间来计算.这是预料之中的.

回到主要问题,应该使用async/await而不是.then原始的承诺?

请记住,async/await仅仅是原始承诺的语法糖,所以不应该对整体表现产生太大影响.但是,它确实使您的代码更加线性,从而消除了开发人员的大量认知开销.

结论是使用你喜欢的.Promise可以被polyfill'd但新的语法不能,所以你可能想在决定使用哪种样式时记住这一点.


一些误解:

从promise链返回的错误堆栈没有提供错误发生位置的线索

事实并非如此.快速检查:

function error() {
    return new Promise(function(res, rej) {
        res(undefined()); // uh oh
    });
}

error().then(console.log, e => console.log("Uh oh!", e.stack));
Run Code Online (Sandbox Code Playgroud)

显示整个错误堆栈,包括位置.


uni*_*nal 8

大多数情况下,答案是"它取决于".

在谈论性能之前,更重要的方面是代码的可维护性和async/ awaitvs raw的限制Promise.

async/ await是顺序执行异步代码的好方法,同时Promise使您能够同时运行异步代码.

async function foo() {
  const a = await backend.doSomething()
  const b = await backend.doAnotherThing()
  return a + b
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,在返回backend.doAnotherThing()之前不会执行backend.doSomething().另一方面:

function foo() {
  Promise.all([backend.doSomething(), backend.doAnotherThing()])
    .then(([a, b]) => {
       return a + b
    })
}
Run Code Online (Sandbox Code Playgroud)

将执行两个调用,并等待两个调用完成.

正如您提到的async/ 的好处await,我个人广泛使用它.除上述情况外.

如果你需要性能和你,那么async/ awaitvs 之间的性能差异Promiseasync/ awaitover 的可读性好处更重要Promise,所有意味着继续.

只要是有意识的选择,你应该没事.

更新:如Derek朕会功夫所述

您可以使用async/ awaitby 获得并行执行:

async function foo() {
  const p1 = backend.doSomething()
  const p2 = backend.doAnotherThing()
  return await p1 + await p2
}
Run Code Online (Sandbox Code Playgroud)

  • 在这一点上它是挑剔的,但你的异步示例可以[重写为](https://jsfiddle.net/DerekL/e3wwfc2p/)同时执行它们.`async/await`和raw promise方法都非常适合同时运行异步代码. (4认同)