[英]What is the difference between JavaScript promises and async await?
我已经在我的应用程序中使用了ECMAScript 6和 ECMAScript 7 功能(感谢 Babel)——移动应用程序和 web。
第一步显然是 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 的特性,其中之一是ASYNC
和AWAIT
关键字/函数。 这些结合起来创造了巨大的奇迹。 我已经开始用async & await
替换我的一些承诺。 它们似乎为编程风格增加了巨大的价值。
同样,这是我的异步等待 function 的伪代码 -
async function myAsyncFunction (myObj) {
var x = new MyDataStore(myObj);
return await x.init();
}
var returnVal = await myAsyncFunction(obj);
撇开语法错误(如果有的话)不谈,我觉得它们都做同样的事情。 我几乎已经能够用 async,waits 代替我的大部分承诺。
当 Promise 做类似的工作时,为什么需要 async,await?
async,await 能解决更大的问题吗? 或者它只是回调地狱的不同解决方案?
正如我之前所说,我可以使用 Promise 和 async,await 来解决同样的问题。 有什么特定的异步等待解决了吗?
补充说明:
我一直在我的 React 项目和 Node.js 模块中广泛使用异步、等待和承诺。 React 尤其是早起的鸟儿,采用了许多 ECMAScript 6 和 ECMAScript 7 特性。
当 Promises 做类似的工作时,为什么需要 async,await ? async,await 是否解决了更大的问题?
async/await
只是让您对异步代码有一种同步的感觉。 这是一种非常优雅的语法糖形式。
对于简单的查询和数据操作,Promises 可以很简单,但是如果您遇到复杂的数据操作和不涉及的场景,如果代码看起来好像是同步的(换句话说,语法本身就是一种async/await
可以绕过的“偶然复杂性”形式)。
如果你有兴趣知道,你可以使用像co
这样的库(与生成器一起)来提供同样的感觉。 已经开发了这样的东西来解决async/await
最终解决的问题(本地)。
Async/Await 在更复杂的场景中提供了更好的语法。 特别是,任何处理循环或某些其他结构(如try
/ catch
。
例如:
while (!value) {
const intermediate = await operation1();
value = await operation2(intermediate);
}
仅使用 Promises,这个例子会更加复杂。
当 Promises 做类似的工作时,为什么需要 async,await ? async,await 是否解决了更大的问题? 或者它只是回调地狱的不同解决方案? 正如我之前所说,我可以使用 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
等待承诺( fetch(url)
)被解析或拒绝。 如果承诺被解析,该值存储在response
变量中,如果承诺被拒绝,它将抛出错误并因此进入catch
块。
我们已经可以看到,使用async
/ await
可能比 promise 链接更具可读性。 当我们使用的 Promise 数量增加时尤其如此。 Promise chaining 和async
/ await
解决了回调地狱的问题,你选择哪种方法取决于个人喜好。
利弊的全面比较。
纯 JavaScript
- 不需要任何额外的库或技术
- 提供最佳性能
- 提供与第三方库的最佳兼容性
- 允许创建临时和更高级的算法
- 可能需要额外的代码和相对复杂的算法
异步(库)
- 简化最常见的控制流模式
- 仍然是基于回调的解决方案
- 很棒的表演
- 引入外部依赖
- 对于高级流程来说可能仍然不够
承诺
- 大大简化了最常见的控制流模式
- 强大的错误处理
- ES2015 规范的一部分
- 保证延迟调用 onFulfilled 和 onRejected
- 需要 promisify 基于回调的 API
- 引入了一个小的性能影响
发电机
- 使非阻塞 API 看起来像阻塞 API
- 简化错误处理
- ES2015 规范的一部分
- 需要一个互补的控制流库
- 仍然需要回调或承诺来实现非顺序流
- 需要 thunkify 或 promisify 非基于生成器的 API
异步等待
- 使非阻塞 API 看起来像阻塞
- 简洁直观的语法
- 需要 Babel 或其他转译器和一些配置才能在今天使用
在需要复杂控制流的情况下,Async/await 可以帮助使您的代码更清晰、更具可读性。 它还生成更易于调试的代码。 并且可以仅通过try/catch
处理同步和异步错误。
我最近写了这篇文章,展示了在一些常见用例中 async/await 优于 promises 的代码示例: JavaScript Async/Await Blows Promises Away 的 6 个原因(教程)
两者都是处理异步代码的方法。 但是两者的执行之间存在差异。 这是工作执行-
诺言
Promise对象表示异步操作的可能完成(或失败)及其结果值。 它是在创建时未必知道的值的代理,它表示异步操作的未来结果。
在执行下一步之前,调用代码可以等待直到实现了诺言。 为此,promise具有一个名为then
的方法,该方法接受一个函数,该函数将在实现诺言时被调用。
异步/等待
调用async
函数时,它将返回Promise
。 当async
函数返回值时, Promise
将使用返回的值进行解析。 当async
函数抛出异常或某个值时,Promise将被抛出的值拒绝。
异步函数可以包含await表达式,该表达式会暂停异步函数的执行并等待传递的Promise的分辨率,然后恢复异步函数的执行并返回解析的值。
异步/等待承诺的优点
Await 语法只是同步代码,因为您必须等到承诺完成或拒绝。 实际上在 await 关键字之后的代码执行将被暂停,直到承诺解决或拒绝。
await/async 通常被称为 promises 的语法糖,让我们等待一些东西(例如 API 调用),让我们错觉它在实际的异步代码中是同步的,这是一个很大的好处。
你想用 async/await 实现的事情可以用 promises 来实现,但是 async/await 的优点。 让我们以这段代码为例:
const makeRequest = () => //promise way
getJSON()
.then(data => {
return data
})
makeRequest();
const makeRequest = async () => { //async await way
const data = await getJSON();
return data;
}
请求()
为什么 async/await 比 promise 更受欢迎?
简洁和干净- 我们不必编写 .then 并创建匿名函数来处理响应,或者为我们不需要使用的变量提供名称数据。 我们还避免了嵌套我们的代码。 async/await 更干净。
错误处理- Async/await 最终可以使用相同的 try/catch 格式处理同步和异步错误。
调试- 使用 async/await 的一个非常好的优势是调试比 promise 容易得多,原因有两个:1)您不能在返回表达式(无正文)的箭头函数中设置断点。 2) 如果您在 .then 块中设置断点并使用调试快捷方式,例如 step-over,调试器将不会移动到后面的 .then,因为它只会“单步执行”同步代码。
错误堆栈- 从承诺链返回的错误堆栈让我们不知道错误发生在哪里并且可能会产生误导。 async/await 为我们提供了从 async/await 指向包含错误的函数的错误堆栈,这是一个非常大的优势。
你真的不应该在你的代码中再使用 var,也看看新的箭头函数语法,它更干净
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.