JavaScript promise和async await有什么区别?


95

我已经在移动应用程序和Web应用程序中使用了ECMAScript 6和ECMAScript 7功能(由于Babel)。

第一步显然是达到ECMAScript 6级别。我学习了许多异步模式,promise(确实很有希望),生成器(不确定为什么使用*符号)等。其中,promise非常适合我的目的。我已经在我的应用程序中使用它们很多次了。

这是我如何实现基本诺言的示例/伪代码-

var myPromise = new Promise(
    function (resolve,reject) {
      var x = MyDataStore(myObj);
      resolve(x);
    });

myPromise.then(
  function (x) {
    init(x);
});

随着时间的流逝,我遇到了ECMAScript 7功能,其中之一是ASYNCAWAIT关键字/功能。这些结合在一起创造了很大的奇迹。我已经开始用代替我的一些诺言async & await。它们似乎为编程风格增加了巨大的价值。

同样,这是我的async,await函数的伪代码,如下所示:

async function myAsyncFunction (myObj) {
    var x = new MyDataStore(myObj);
    return await x.init();
}
var returnVal = await myAsyncFunction(obj);

撇开语法错误(如果有的话),他们俩所做的事情完全是我的感觉。我几乎可以用异步替换掉我的大部分诺言。

为什么诺言做类似的工作时需要异步等待?

异步等待解决更大的问题吗?还是只是针对回调地狱的另一种解决方案?

如前所述,我能够使用promise和async,等待解决相同的问题。异步等待解决了什么具体问题?

补充笔记:

我已经在我的React项目和Node.js模块中广泛使用异步,唤醒和承诺。React特别是早起的鸟儿,并采用了许多ECMAScript 6和ECMAScript 7功能。


3
您的第一个代码块似乎将诺言用于同步操作。为什么要这么做?从本质上讲,同步是更容易编写代码的,因此应该没有理由将同步操作包装到promise中并迫使它现在变为异步。
jfriend00

@ jfriend00是的,您是对的。编辑了代码。谢谢。
bozzmob

2
您仍在尝试使用具有同步功能的异步工具-现在在两个代码块中。为什么?
jfriend00

@ jfriend00好的。这里有我的代码gist.github.com/bozzmob/26d38b83dc37d1be37f5。请您告诉我我做错了什么吗?
bozzmob

10
听起来您只需要阅读一堆就可以了解异步和等待的意义。这里有一些文章:长路异步/等待中的JavaScript简化异步ES7异步功能编码驯服与ES7异步兽
jfriend00

Answers:


74

为什么Promises做类似的工作时需要异步等待?异步等待解决更大的问题吗?

async/await只是给您异步代码的同步感觉。这是一种非常优雅的语法糖。

对于简单的查询和数据操作,Promises可能很简单,但是如果您遇到了复杂的数据操作和不涉及任何内容的场景,那么如果代码看起来好像是同步的,则更容易理解正在发生的情况(换句话说,语法本身就是一种“偶然的复杂性”,async/await可以绕开。

如果您想知道,可以使用类似co(与生成器一起)的库来提供相同的感觉。已经开发了类似的方法来解决async/await最终解决的问题(本机)。


请您详细说明“偶然的复杂性”是什么意思?另外,在性能方面,两者之间没有区别吗?
bozzmob

@bozzmob,shaffner.us/ cs/papers/ tarpit.pdf <-他解释了其中的“偶然复杂性”。至于您的性能问题,我对此表示怀疑,尤其是对于V8引擎而言。我敢肯定那里有一些性能测试,但是我不会为此担心太多。不必要时,不要在微优化上浪费时间。
Josh Beam

1
非常感谢!这是我从您那里获得的一些重要信息。是的,不会研究微观优化。
bozzmob 2015年

我发现此说明有用nikgrozev.com/2015/07/14/…–
mwojtera

33

在更复杂的情况下,异步/等待提供了更好的语法。特别是处理循环或某些其他构造(例如try/)的任何事物catch

例如:

while (!value) {
  const intermediate = await operation1();
  value = await operation2(intermediate);
}

仅使用Promises,此示例将更加复杂。


这是一个很好的例子。那么,在性能方面,两者之间没有区别吗?在代码中使用哪个更好?看到您的示例之后,Async Await似乎更好。
bozzmob 2015年

1
@bozzmob:性能没有差异。如果您习惯使用异步/等待,那么我建议您使用它。我自己还没有使用它,因为它实际上并不是官方标准的一部分。
史蒂芬·克雷里

是的,我同意它不是标准的一部分,但是,对于ReactJS(专门针对本机反应),我被迫在代码的某些部分使用它。因此,其中一半是承诺,另一半是异步唤醒。所以,我问你那些问题。感谢您有需要的信息。
bozzmob

1
我认为当没有人在他们的代码示例中使用try / catch块时,很多人会感到困惑和/或被误导。
Augie Gardner

你是说那样吗?const getValue = value => value || operation1().then(operation2).then(getValue);
Sharcoux '18年

13

为什么Promises做类似的工作时需要异步等待?异步等待解决更大的问题吗?还是只是用于回调地狱的另一种解决方案?如前所述,我可以使用Promises和Async,Await解决相同的问题。Async Await解决了什么具体问题?

首先,您必须了解async/ await语法只是语法糖,旨在增强承诺。实际上,async函数的返回值是一个承诺。async/ await语法使我们有可能以同步方式编写异步代码。这是一个例子:

承诺链:

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}

Async 功能:

async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

在上面的示例中,await等待promise(fetch(url))被解决或被拒绝。如果承诺被解决,则值将存储在response变量中,如果承诺被拒绝,则将抛出错误并进入程序catch段。

我们已经可以看到,使用async/ await可能比诺言链更具可读性。当我们使用的承诺数量增加时,尤其如此。Promise链接和async/ await解决了回调地狱的问题,您选择哪种方法取决于个人喜好。


7

全面比较优缺点。

纯JavaScript

  • 优点
  • 不需要任何其他库或技术
  • 表现最佳
  • 提供与第三方库的最佳兼容性
  • 允许创建临时和更高级的算法
  • 缺点
  • 可能需要额外的代码和相对复杂的算法

异步(库)

  • 优点
  • 简化最常见的控制流模式
  • 仍然是基于回调的解决方案
  • 很棒的表演
  • 缺点
  • 引入外部依赖
  • 对于高级流可能仍然不够

承诺

  • 优点
  • 极大地简化了最常见的控制流模式
  • 强大的错误处理
  • ES2015规范的一部分
  • 确保onFulfilled和onRejected的延迟调用
  • 缺点
  • 需要承诺基于回调的API
  • 引入了较小的性能影响

发电机

  • 优点
  • 使非阻塞API看起来像一个阻塞的API
  • 简化错误处理
  • ES2015规范的一部分
  • 缺点
  • 需要一个补充控制流库
  • 仍然需要回调或承诺以实现非顺序流
  • 需要对基于非生成器的API进行分类处理

异步等待

  • 优点
  • 使非阻塞API看起来像阻塞
  • 简洁直观的语法
  • 缺点
  • 要求今天使用Babel或其他编译器以及一些配置

这是从哪里复制的?至少其中一些是在Node.js设计模式(第二版)(ISBN-10:1785885588)一书中的136-137页上
Peter Mortensen

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.