JavaScript 承诺和异步等待之间的区别是什么?

我已经在我的应用程序中使用了 ECMAScript 6和 ECMAScript 7的特性(感谢 Babel)——无论是手机还是网络。

第一步显然是到 ECMAScript 6级。我学到了许多异步模式,承诺(这是真正有希望的) ,生成器(不确定为什么 * 符号) ,等等。 除此之外,承诺很符合我的目的。我在我的应用程序中经常使用它们。

下面是我如何实现一个基本承诺的示例/伪代码-

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 function myAsyncFunction (myObj) {
var x = new MyDataStore(myObj);
return await x.init();
}
var returnVal = await myAsyncFunction(obj);

撇开语法错误(如果有的话)不谈,我觉得它们做的事情完全一样。我几乎已经能够用异步代替我的大部分承诺,等待。

为什么当承诺执行类似的工作时需要异步、等待?

异步,等待解决一个更大的问题吗? 或者它只是一个不同的解决方案回调地狱?

如前所述,我能够使用承诺和异步,等待解决同样的问题。是否有任何特定的异步等待解决?

附加说明:

我一直在我的 React 项目和 Node.js 模块中广泛使用异步、等待和承诺。 反应特别是早起的鸟,采用了很多 ECMAScript 6和 ECMAScript 7的特性。

85897 次浏览

Async/Await 在更复杂的场景中提供了更好的语法。特别是,任何处理循环或某些其他构造(如 try/catch)的内容。

例如:

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

仅仅使用承诺,这个例子就要复杂得多。

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

async/await只是给你一种异步代码的同步感觉。

对于简单的查询和数据操作,承诺可以很简单,但是如果你遇到复杂的数据操作和其他情况,如果代码简单的 看起来就像同步一样(换句话说,语法本身就是一种“附带的复杂性”,async/await可以绕过它) ,那么你就更容易理解发生了什么。

如果您感兴趣,可以使用类似 co的库(以及生成器)来提供同样的感觉。像这样的东西已经被开发用来解决 async/await最终(本地)解决的问题。

在需要复杂控制流程的情况下,Async/wait 可以帮助您使代码更清晰、更易读。它还生成更加调试友好的代码。并且使得仅使用 try/catch就可以处理同步和异步错误。

我最近写了这篇文章,通过代码示例展示了异步/等待相对于某些常见用例中的承诺的优势: 返回文章页面为什么 JavaScript 异步/等待打击承诺译者:

为什么异步,等待需要时,承诺做 类似的工作? 异步,等待解决一个更大的问题? 或者它只是一个 不同的解决方案回到地狱? 正如我之前所说,我能够 使用承诺和 Async,等待解决同样的问题。有没有 异步等待解决了什么具体问题吗?

首先,您必须理解 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可能比承诺链更具可读性。当我们使用的承诺数量增加时,这一点尤其正确。承诺链和 async/await都解决了回调地狱的问题,你选择哪种方法是个人喜好的问题。

等待/异步通常被称为承诺的语法糖,让我们等待一些东西(例如 API 调用) ,让我们以为它在实际的异步代码中是同步的,这是一个很大的好处。

您希望通过异步/等待实现的功能可以通过承诺来实现(但是没有异步/等待的优点)。让我们以这段代码为例:

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


makeRequest();


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


makeRequest()

为什么异步/等待优于承诺?

  1. 简洁明了 -我们不必编写 .then并创建一个匿名函数来处理响应,也不必为不需要使用的变量提供名称数据。我们还避免了嵌套代码。异步/等待要干净得多。

  2. 错误处理 -Async/wait 最终使用相同的 try/catch 格式处理同步和异步错误成为可能。

  3. 调试 -使用异步/等待时的一个非常好的优势是调试比承诺要容易得多,原因有二: 1)不能在返回表达式的箭头函数中设置断点(没有主体)。2)如果你在 .then块中设置了一个断点,并且使用了类似跨越这样的调试快捷方式,那么调试器将不会移动到下面的 .then,因为它只是“跨越”同步代码。

  4. 错误堆栈 -从承诺链返回的错误堆栈让我们不知道错误发生在哪里,可能会误导我们。Sync/wait 为我们提供了错误堆栈,这些错误堆栈来自于包含错误的函数,这是一个非常大的优势。