前言

在过去很长的一段时间里,JavaScript开发人员不得不依赖回调来处理异步代码。如果遇到赋值的逻辑,会发现,特别难处理维护,代码看起来也特别的糟糕。

现在,由于 Async / Await 的出现,编写JavaScript代码再也不用像以前一样了。

10分钟了解JavaScript Async/Await函数

什么是 Async/Await?

Async / Await是一个备受期待的JavaScript功能,它使异步函数的使用更加愉快和易于理解。它构建在Promises之上,并与所有现有的基于Promise的API兼容。

该名称来自async和await - 这两个关键字将帮助我们清理异步代码:

Async - 声明一个异步函数 (async function someName(){…})。
1、自动将常规函数转换为承诺。
2、当调用异步函数时,请使用其主体中返回的内容进行解析。
3、异步函数允许使用await。

Await - 暂停异步函数的执行。(var result = await someAsyncCall();)。
1、当置于Promise调用前面时,wait强制其余代码等待,直到该Promise完成并返回结果。
2、Await仅适用于Promises,它不适用于回调。
3、await只能在异步函数内部使用。

下面是一个简单的例子:

假设我们想从服务器上获取一些JSON文件。我们将编写一个使用AXIOS库的函数,并将HTTP GET请求发送到 xxx.json。 我们必须等待服务器响应,所以这个HTTP请求自然是异步的。

下面我们可以看到相同的函数实现了两次。首先是Promise,然后是第二次使用异步/等待。

// Promise function getJSON(){ // 为了使函数阻塞,我们手动创建一个Promise。 return new Promise( function(resolve) { axios.get('https://www.javanx.cn/example.json') .then( function(json) { // 我们使用resolve返回结果 resolve(json); }); }); } // Async/Await // async关键字将自动创建一个新的Promise并返回它 async function getJSONAsync(){ // wait关键字使我们不必编写.then()块 let json = await axios.get('https://tutorialzine.com/misc/files/example.json'); // GET请求的结果在JSON变量中可用 // 我们返回它,就像正常同步函数一样 return json; }

很明显,代码的Async / Await版本更短,更容易阅读。除了使用的语法之外,两个函数完全相同 - 它们都返回Promises并使用axios的JSON响应来解析。我们可以这样调用我们的异步函数:

getJSONAsync().then( function(result) { // Do something with result. });

那么,Async / Await 会比 Promise更好嘛?

10分钟了解JavaScript Async/Await函数

一点都不。使用Async / Await时,我们仍在使用Promise。从长远来看,对Promise的良好理解实际上对您有很大的好处。

甚至有一些用例Async / Await并不能解决问题,我们不得不回到Promise上,需求答案。

一个这样的场景,当我们需要进行多个独立的异步调用并等待所有这些调用完成时。

如果我们尝试使用async和await执行此操作,将发生以下情况:

async function getABC() { let A = await getValueA(); // 2 second to finish let B = await getValueB(); // 4 second to finish let C = await getValueC(); // 3 second to finish return A*B*C; }

每个调用将等待前一个返回结果。由于我们一次只进行一次调用,整个功能从开始到结束需要9秒(2 + 4 + 3)。

这不是最佳解决方案,因为三个变量A,B和C不相互依赖。换句话说,在我们得到B之前,我们不需要知道A的值。我们可以同时得到它们并且等待几秒钟。

要同时发送所有请求,需要Promise.all()。这将确保执行后面函数之前我们仍然拥有所有结果,但异步调用将并行触发,而不是一个接一个地触发。

async function getABC() { // Promise.all()允许我们同时发送所有请求。 let results = await Promise.all([ getValueA, getValueB, getValueC ]); return results.reduce((total,value) => total * value); }

这样,该功能将花费更少的时间。 getValueB和getValueC调用将在getValueB结束时完成。我们将有效地将执行时间减少到最慢请求的时间(getValueB - 4秒),而不是时间的总和。

处理Async / Await中的错误

10分钟了解JavaScript Async/Await函数

Async / Await的另一个好处是它允许我们在try / catch块中捕获任何意外错误。我们只需要像这样包装我们的Await:

async function doSomethingAsync(){ try { // 此异步调用可能会失败. let result = await someAsyncCall(); } catch(error) { // 我们将在这里发现错误 } }

catch子句将处理等待的异步调用,或我们在try块中编写的任何其他失败代码所引发的错误。

如果情况需要,我们还可以在执行异步函数时捕获错误。因为所有异步函数都返回Promise,所以在调用它们时我们可以简单地包含一个.catch()事件处理程序。

// 没有try / catch块的异步函数。 async function doSomethingAsync(){ // This async call may fail. let result = await someAsyncCall(); return result; } // 我们在调用函数时捕获错误 doSomethingAsync(). .then(successHandler) .catch(errorHandler);

根据自己的喜好,选择之中即可。同时使用try/catch和.catch()很可能会导致问题。

浏览器支持

10分钟了解JavaScript Async/Await函数

Async / Await已在大多数主流浏览器中提供。排除IE11- 所有其他供应商将识别async/await代码,而无需外部库。

结语

通过添加Async / Await,JavaScript语言在代码可读性和易用性方面取得了巨大的飞跃。编写类似于常规同步函数的异步代码的能力将受到初学者和经验丰富的编码人员的青睐。