简体   繁体   English

JavaScript 承诺和异步等待有什么区别?

[英]What is the difference between JavaScript promises and async await?

I have been using ECMAScript 6 and ECMAScript 7 features already (thanks to Babel) in my applications - both mobile and web.我已经在我的应用程序中使用了ECMAScript 6和 ECMAScript 7 功能(感谢 Babel)——移动应用程序和 web。

The first step obviously was to ECMAScript 6 levels.第一步显然是 ECMAScript 6 级别。 I learnt many async patterns, the promises (which are really promising), generators (not sure why the * symbol), etc. Out of these, promises suited my purpose pretty well.我学习了许多异步模式、promise(非常有前途)、生成器(不确定为什么使用 * 符号)等等。其中,promise 非常适合我的目的。 And I have been using them in my applications quite a lot.我一直在我的应用程序中使用它们很多。

Here is an example/pseudocode of how I have implemented a basic promise-这是我如何实现基本承诺的示例/伪代码-

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

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

As time passed, I came across ECMAScript 7 features, and one of them being ASYNC and AWAIT keywords/functions.随着时间的推移,我遇到了 ECMAScript 7 的特性,其中之一是ASYNCAWAIT关键字/函数。 These in conjunction do great wonders.这些结合起来创造了巨大的奇迹。 I have started to replace some of my promises with async & await .我已经开始用async & await替换我的一些承诺。 They seem to add great value to programming style.它们似乎为编程风格增加了巨大的价值。

Again, here is a pseudocode of how my async, await function looks like-同样,这是我的异步等待 function 的伪代码 -

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

Keeping the syntax errors (if any) aside, both of them do the exact same thing is what I feel.撇开语法错误(如果有的话)不谈,我觉得它们都做同样的事情。 I have almost been able to replace most of my promises with async,awaits.我几乎已经能够用 async,waits 代替我的大部分承诺。

Why is async,await needed when promises do a similar job?当 Promise 做类似的工作时,为什么需要 async,await?

Does async,await solve a bigger problem? async,await 能解决更大的问题吗? Or was it just a different solution to callback hell?或者它只是回调地狱的不同解决方案?

As I said earlier, I am able to use promises and async,await to solve the same problem.正如我之前所说,我可以使用 Promise 和 async,await 来解决同样的问题。 Is there anything specific that async await solved?有什么特定的异步等待解决了吗?

Additional notes:补充说明:

I have been using async,awaits and promises in my React projects and Node.js modules extensively.我一直在我的 React 项目和 Node.js 模块中广泛使用异步、等待和承诺。 React especially have been an early bird and adopted a lot of ECMAScript 6 and ECMAScript 7 features. React 尤其是早起的鸟儿,采用了许多 ECMAScript 6 和 ECMAScript 7 特性。

Why is async,await needed when Promises does similar job?当 Promises 做类似的工作时,为什么需要 async,await ? Does async,await solve a bigger problem? async,await 是否解决了更大的问题?

async/await simply gives you a synchronous feel to asynchronous code. async/await只是让您对异步代码有一种同步的感觉。 It's a very elegant form of syntactical sugar.这是一种非常优雅的语法糖形式。

For simple queries and data manipulation, Promises can be simple, but if you run into scenarios where there's complex data manipulation and whatnot involved, it's easier to understand what's going on if the code simply looks as though it's synchronous (to put it another way, syntax in and of itself is a form of "incidental complexity" that async/await can get around).对于简单的查询和数据操作,Promises 可以很简单,但是如果您遇到复杂的数据操作和不涉及的场景,如果代码看起来好像是同步的(换句话说,语法本身就是一种async/await可以绕过的“偶然复杂性”形式)。

If you're interested to know, you can use a library like co (alongside generators) to give the same sort of feel.如果你有兴趣知道,你可以使用像co这样的库(与生成器一起)来提供同样的感觉。 Things like this have been developed to solve the problem that async/await ultimately solves (natively).已经开发了这样的东西来解决async/await最终解决的问题(本地)。

Async/Await provide a much nicer syntax in more complex scenarios. Async/Await 在更复杂的场景中提供了更好的语法。 In particular, anything dealing with loops or certain other constructs like try / catch .特别是,任何处理循环或某些其他结构(如try / catch

For example:例如:

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

This example would be considerably more convoluted just using Promises.仅使用 Promises,这个例子会更加复杂。

Why is async,await needed when Promises does similar job?当 Promises 做类似的工作时,为什么需要 async,await ? Does async,await solve a bigger problem? async,await 是否解决了更大的问题? or was it just a different solution to callback hell?或者它只是回调地狱的不同解决方案? As I said earlier, I am able to use Promises and Async,Await to solve the same problem.正如我之前所说,我可以使用 Promises 和 Async,Await 来解决同样的问题。 Is there anything specific that Async Await solved? Async Await 解决了什么具体问题吗?

The first things you have to understand that async / await syntax is just syntactic sugar which is meant to augment promises.首先你必须了解async / await语法只是语法糖,它旨在增强承诺。 In fact the return value of an async function is a promise.事实上, async函数的返回值是一个承诺。 async / await syntax gives us the possibility of writing asynchronous in a synchronous manner. async / await语法给了我们以同步方式编写异步的可能性。 Here is an example:下面是一个例子:

Promise chaining:承诺链:

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

Async function: Async功能:

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

In the above example the await waits for the promise ( fetch(url) ) to be either resolved or rejected.在上面的例子中, await等待承诺( fetch(url) )被解析或拒绝。 If the promise is resolved the value is stored in the response variable, and if the promise is rejected it would throw an error and thus enter the catch block.如果承诺被解析,该值存储在response变量中,如果承诺被拒绝,它将抛出错误并因此进入catch块。

We can already see that using async / await might be more readable than promise chaining.我们已经可以看到,使用async / await可能比 promise 链接更具可读性。 This is especially true when the amount of promises which we are using increases.当我们使用的 Promise 数量增加时尤其如此。 Both Promise chaining and async / await solve the problem of callback hell and which method you choose is matter of personal preference. Promise chaining 和async / await解决了回调地狱的问题,你选择哪种方法取决于个人喜好。

Full comparison with pros and cons.利弊的全面比较。

Plain JavaScript纯 JavaScript

  • Pros优点
  • Does not require any additional libraries or technology不需要任何额外的库或技术
  • Offers the best performance提供最佳性能
  • Provides the best level of compatibility with third-party libraries提供与第三方库的最佳兼容性
  • Allows the creation of ad hoc and more advanced algorithms允许创建临时和更高级的算法
  • Cons缺点
  • Might require extra code and relatively complex algorithms可能需要额外的代码和相对复杂的算法

Async (library)异步(库)

  • Pros优点
  • Simplifies the most common control flow patterns简化最常见的控制流模式
  • Is still a callback-based solution仍然是基于回调的解决方案
  • Good performance很棒的表演
  • Cons缺点
  • Introduces an external dependency引入外部依赖
  • Might still not be enough for advanced flows对于高级流程来说可能仍然不够

Promises承诺

  • Pros优点
  • Greatly simplifies the most common control flow patterns大大简化了最常见的控制流模式
  • Robust error handling强大的错误处理
  • Part of the ES2015 specification ES2015 规范的一部分
  • Guarantees deferred invocation of onFulfilled and onRejected保证延迟调用 onFulfilled 和 onRejected
  • Cons缺点
  • Requires promisify callback-based APIs需要 promisify 基于回调的 API
  • Introduces a small performance hit引入了一个小的性能影响

Generators发电机

  • Pros优点
  • Makes non-blocking API look like a blocking one使非阻塞 API 看起来像阻塞 API
  • Simplifies error handling简化错误处理
  • Part of ES2015 specification ES2015 规范的一部分
  • Cons缺点
  • Requires a complementary control flow library需要一个互补的控制流库
  • Still requires callbacks or promises to implement non-sequential flows仍然需要回调或承诺来实现非顺序流
  • Requires thunkify or promisify nongenerator-based APIs需要 thunkify 或 promisify 非基于生成器的 API

Async await异步等待

  • Pros优点
  • Makes non-blocking API look like blocking使非阻塞 API 看起来像阻塞
  • Clean and intuitive syntax简洁直观的语法
  • Cons缺点
  • Requires Babel or other transpilers and some configuration to be used today需要 Babel 或其他转译器和一些配置才能在今天使用

Async/await can help make your code cleaner and more readable in cases where you need complicated control flow.在需要复杂控制流的情况下,Async/await 可以帮助使您的代码更清晰、更具可读性。 It also produces more debug-friendly code.它还生成更易于调试的代码。 And makes it possible to handle both synchronous and asynchronous errors with just try/catch .并且可以仅通过try/catch处理同步和异步错误。

I recently wrote this post showing the advantages of async/await over promises in some common use cases with code examples: 6 Reasons Why JavaScript Async/Await Blows Promises Away (Tutorial)我最近写了这篇文章,展示了在一些常见用例中 async/await 优于 promises 的代码示例: JavaScript Async/Await Blows Promises Away 的 6 个原因(教程)

Both are the ways to handle asynchronous code. 两者都是处理异步代码的方法。 But there is a difference between the execution of each. 但是两者的执行之间存在差异。 Here is the working execution - 这是工作执行-

Promise 诺言

The Promise object represents the possible completion (or failure) of an asynchronous operation and its resulting value. Promise对象表示异步操作的可能完成(或失败)及其结果值。 It is a proxy for a value not necessarily known at its creation time, and it represents the future result of an asynchronous operation. 它是在创建时未必知道的值的代理,它表示异步操作的未来结果。

The calling code can wait until that promise is fulfilled before executing the next step. 在执行下一步之前,调用代码可以等待直到实现了诺言。 To do so, the promise has a method named then , which accepts a function that will be invoked when the promise has been fulfilled. 为此,promise具有一个名为then的方法,该方法接受一个函数,该函数将在实现诺言时被调用。

Async/await 异步/等待

When an async function is called, it returns a Promise . 调用async函数时,它将返回Promise When the async function returns a value, the Promise will be resolved with the returned value. async函数返回值时, Promise将使用返回的值进行解析。 When the async function throws an exception or some value, the Promise will be rejected with the thrown value. async函数抛出异常或某个值时,Promise将被抛出的值拒绝。

An async function can contain an await expression, which pauses the execution of the async function and waits for the passed Promise's resolution, and then resumes the async function's execution and returns the resolved value. 异步函数可以包含await表达式,该表达式会暂停异步函数的执行并等待传递的Promise的分辨率,然后恢复异步函数的执行并返回解析的值。

pros of async/await over promise 异步/等待承诺的优点

  • Async/await is constructed in order to give a clean syntax to the continuation semantics of asynchronous operations. 构造Async / await是为了给异步操作的延续语义提供清晰的语法。
  • It avoids callback/promise hell. 它避免了回调/承诺地狱。

Await syntax is simply synchronous code because you have to wait until the promise is fulfilled or rejected. Await 语法只是同步代码,因为您必须等到承诺完成或拒绝。 Actually code execution after await keyword will be suspended until the promise resolve or reject.实际上在 await 关键字之后的代码执行将被暂停,直到承诺解决或拒绝。

await/async are often referred to as syntactic sugar to promises and let us wait for something (eg an API call), giving us the illusion that it is synchronous in an actual asynchronous code, which is a great benefit. await/async 通常被称为 promises 的语法糖,让我们等待一些东西(例如 API 调用),让我们错觉它在实际的异步代码中是同步的,这是一个很大的好处。

The things you want to acheive with async/await is is possible with promises but the advantages of async/await.你想用 async/await 实现的事情可以用 promises 来实现,但是 async/await 的优点。 let's an example with this code:让我们以这段代码为例:

const makeRequest = () => //promise way
  getJSON()
    .then(data => {
      return data
    })

makeRequest();

const makeRequest = async () => { //async await way
  const data = await getJSON();
  return data;
 }

makeRequest()请求()

Why is async/await prefered over promise?为什么 async/await 比 promise 更受欢迎?

  1. Concise and clean - We didn't have to write .then and create an anonymous function to handle the response, or give a name data to a variable that we don't need to use.简洁和干净- 我们不必编写 .then 并创建匿名函数来处理响应,或者为我们不需要使用的变量提供名称数据。 We also avoided nesting our code.我们还避免了嵌套我们的代码。 async/await is a lot cleaner. async/await 更干净。

  2. Error handling - Async/await makes it finally possible to handle both synchronous and asynchronous errors with the same try/catch format.错误处理- Async/await 最终可以使用相同的 try/catch 格式处理同步和异步错误。

  3. Debugging - A really good advantage when using async/await is that it's much easier to debug then promises for 2 reasons: 1) you can't set breakpoints in arrow functions that return expressions (no body).调试- 使用 async/await 的一个非常好的优势是调试比 promise 容易得多,原因有两个:1)您不能在返回表达式(无正文)的箭头函数中设置断点。 2) if you set a breakpoint inside a .then block and use debug shortcuts like step-over, the debugger will not move to the the following .then because it only “steps” through synchronous code. 2) 如果您在 .then 块中设置断点并使用调试快捷方式,例如 step-over,调试器将不会移动到后面的 .then,因为它只会“单步执行”同步代码。

  4. Error stacks - The error stack returned from promises chain gives us no idea of where the error occured and can be misleading.错误堆栈- 从承诺链返回的错误堆栈让我们不知道错误发生在哪里并且可能会产生误导。 async/await gives us the error stack from async/await points to the function that contains the error which is a really big advantage. async/await 为我们提供了从 async/await 指向包含错误的函数的错误堆栈,这是一个非常大的优势。

你真的不应该在你的代码中再使用 var,也看看新的箭头函数语法,它更干净

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM