我已经在我的应用程序(移动和网络)中使用了 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 个特性,其中之一是 ASYNC
和 AWAIT
关键字/函数。这些结合起来创造了巨大的奇迹。我已经开始用 async & await
替换我的一些承诺。它们似乎为编程风格增加了巨大的价值。
同样,这是我的异步等待函数的伪代码 -
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
只是让您对异步代码有一种同步的感觉。这是一种非常优雅的语法糖形式。
对于简单的查询和数据操作,Promise 可以很简单,但如果您遇到复杂数据操作和其他不涉及的场景,如果代码只是 看起来 就好像它是同步的,就更容易理解发生了什么(换句话说,语法本身就是一种 async/await
可以解决的“偶然复杂性”形式)。
如果您有兴趣了解,可以使用 co
之类的库(与生成器一起)来提供相同的感觉。已经开发出类似的东西来解决 async/await
最终解决的问题(本机)。
Async/Await 在更复杂的场景中提供了更好的语法。特别是处理循环或某些其他构造(如 try
/catch
)的任何内容。
例如:
while (!value) {
const intermediate = await operation1();
value = await operation2(intermediate);
}
仅使用 Promises,此示例将更加复杂。
const getValue = value => value || operation1().then(operation2).then(getValue);
当 Promises 做类似的工作时,为什么需要 async,await ? async,await 能解决更大的问题吗?还是只是回调地狱的不同解决方案?正如我之前所说,我可以使用 Promises 和 Async,Await 来解决同样的问题。 Async Await 解决了什么具体问题?
首先您必须了解 async
/await
语法只是语法糖,旨在增强 Promise。事实上,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)
) 被解决或拒绝。如果 promise 被解决,则值存储在 response
变量中,如果 promise 被拒绝,则会抛出错误并因此进入 catch
块。
我们已经可以看到,使用 async
/await
可能比 Promise 链接更具可读性。当我们使用的 Promise 数量增加时尤其如此。 Promise 链和 async
/await
都解决了回调地狱的问题,您选择哪种方法是个人喜好问题。
在您需要复杂的控制流的情况下,异步/等待可以帮助您的代码更清晰、更具可读性。它还生成更易于调试的代码。并且只需 try/catch
即可处理同步和异步错误。
我最近写了这篇文章,通过代码示例展示了在一些常见用例中 async/await 相对于 Promise 的优势:6 Reasons Why JavaScript Async/Await Blows Promises Away (Tutorial)
await/async 通常被称为 promise 的语法糖,让我们等待某些东西(例如 API 调用),给我们一种在实际异步代码中它是同步的错觉,这是一个很大的好处。
你想通过 async/await 实现的事情可以通过 Promise 实现(但没有 async/await 的优势)。让我们以这段代码为例:
const makeRequest = () => //promise way
getJSON()
.then(data => {
return data
})
makeRequest();
const makeRequest = async () => { //async await way
const data = await getJSON();
return data;
}
makeRequest()
为什么 async/await 比 promise 更受欢迎?
简洁明了 - 我们不必编写 .then 并创建一个匿名函数来处理响应,或者为我们不需要使用的变量提供名称数据。我们还避免了嵌套代码。 async/await 要干净得多。错误处理 - Async/await 最终可以使用相同的 try/catch 格式处理同步和异步错误。调试 - 使用 async/await 的一个非常好的优势是它比 Promise 更容易调试,原因有两个:1) 你不能在返回表达式的箭头函数中设置断点(没有正文)。 2) 如果您在 .then 块中设置断点并使用调试快捷方式(如 step-over),调试器将不会移动到以下 .then ,因为它只会“步进”同步代码。错误堆栈 - 从承诺链返回的错误堆栈让我们不知道错误发生在哪里,并且可能会产生误导。 async/await 为我们提供了从 async/await 指向包含错误的函数的错误堆栈,这是一个非常大的优势。
Await 语法只是简单的同步代码,因为您必须等到 promise 被履行或被拒绝。实际上 await 关键字之后的代码执行将被暂停,直到 promise 解决或拒绝。