JavaScript Async / Await在10分钟内解释
在最长的时间里,JavaScript开发人员不得不依赖回调来处理异步代码。
结果,我们中的许多人都经历过回调地狱...
谢天谢地,然后(或者我们应该说 .then)来了Promises。他们为回调提供了更有组织的替代方案,并且大多数社区很快转而使用它们。现在,随着最新添加的Async / Await,编写JavaScript代码即将变得更好!
什么是async/await?
async- 声明一个异步函数(async function someName(){...})
- 自动将常规函数转换为Promise;
- 当被调用的异步函数解析为它们体内返回的内容时;
- 异步功能可以使用await
await - 暂停执行异步功能。(var result = await someAsyncCall();)
- 当置于Promise调用之前时,await强制其余代码等待Promise完成并返回结果;
- Await仅适用于Promises,它不适用于回调;
- Await只能在 async 函数内部使用
下面一个简单的例子,希望能够解决问题:
假设我们想从服务器获取一些JSON文件。我们将编写一个使用axios库并发送HTTP GET请求
的函数https://tutorialzine.com/misc/files/example.json。我们必须等待服务器响应,因此这个HTTP请求自然会是异步的。
我们将看到两次执行相同的功能。首先使用Promise,然后第二次使用Async / Await
// Promise
function getJSON(){
// 创建一个Promise
return new Promise( function(resolve) {
axios.get('https://tutorialzine.com/misc/files/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');
// 请求的结果赋值给json变量并返回
return json;
}
很明显,代码的Async / Await版本更短,更容易阅读。除了使用的语法之外,两个函数完全相同 - 它们都返回Promises并使用axios的JSON响应来解析。我们可以像这样调用我们的异步函数:
getJSONAsync()。then(function(result) {
//用result做一些事情。
});
Async / Await是否会使Promise过时
不会。使用Async / Await时,我们仍在使用Promise。甚至有一些用例Async / Await没有削减它,我们不得不回到Promises寻求帮助。一个这样的场景是当我们需要进行多个独立的异步调用并等待所有这些调用完成时。
如果我们尝试使用async和await执行此操作,将发生以下情况:
async function getABC() {
let A = await getValueA(); // getValueA需要2秒才能完成
let B = await getValueB(); // etValueB需要4秒才能完成
let C = await getValueC(); // getValueC需要3秒才能完成
return A*B*C;
}
每个等待调用将等待前一个返回结果。由于我们一次只进行一次调用,整个功能从开始到结束需要9秒(2 + 4 + 3)。
这不是一个最佳的解决方案,因为这三个变量A,B以及C不依赖于彼此。换句话说,我们不需要知道A之前的价值B。我们可以同时获得它们并且等待几秒钟。要在同一时间发送所有请求,Promise.all()则需要。这将确保在继续之前我们仍然拥有所有结果,但异步调用将并行触发,而不是一个接一个地触发。
async function getABC() {
// Promise.all() 允许同时发送所有请求。
let results = await Promise.all([ getValueA, getValueB, getValueC ]);
return results.reduce((total,value) => total * value);
}
这样,该功能将花费更少的时间。GetValueA和GetValueC调用将在GetValueB时完成。我们将有效地将执行时间减少到最慢请求的时间(getValueB - 4秒),而不是时间的总和。
处理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(){
// 此异步调用可能会失败
let result = await someAsyncCall();
return result;
}
// 在调用该函数捕获错误。
doSomethingAsync().
.then(successHandler)
.catch(errorHandler);
选择你喜欢的错误处理方法并坚持下去是很重要的。同时使用try/catch和.catch()很可能会导致问题。
浏览器支持
Async / Await已在大多数主流浏览器中提供。这仅排除IE11 - 所有其他供应商将识别您的异步/等待代码,而无需外部库。
异步/等待浏览器支持
转载自:https://juejin.cn/post/6844903874818473998