我正在参加「掘金·启航计划」
前言
Promise 系列 | 开篇 – 你对 Promise 的基本特性了解多少
Promise 系列 | 基础篇 – 3 个对象方法和 6 个类方法
Promise 系列 | 进阶篇 – 手写 Promise 特别行动
前面的几篇文章我们全面学习了 Promise 的相关知识,不过在我们实际开发中使用 async/await 的情况也是很多的,而且比较重要。
async/await
香在哪里呢 ?在处理异步代码时,和 Promise 又有什么差别呢 ?
async
async
用于声明一个异步函数,async 函数是 AsyncFunction 构造函数的实例
定义一个 async 异步函数,可以使用这三种方法:
async function foo() {}
const foo = async () => {}
class Example {
async foo() {}
}
这和普通的函数有什么区别呢 ? 答:基本上没有区别。我们看一下 ?
讲道理,你作为一个异步函数不应该让同步代码先行吗,怎么自己还插队呢
因为它目前还不是一个完全的异步函数,而且异步执行的作用域也不对,具体的内容会在后面讲到
但我们会发现这个 foo() 函数竟然是一个 Promise
前面已经学了 Promise 了,不知道这个 “Promise” 是不是正经 Promise 呢
调一个 then 方法试试能不能接收到 foo()
的值:
async function foo() {
console.log(1);
console.log(2);
}
foo().then(res => {
console.log(res); // undefined
})
我们发现用 async 定义的函数 foo()
,真的可以调用 then() 方法
res 的值是 undefined 的根本原因是 foo()
函数没有返回值,假定一个返回值重写
async function foo() {
// ...
return 200
}
foo().then(res => {
console.log(res); // 200
})
学习过前几篇文章的小伙伴们,这里你可以尝试将返回值定义为一个 thenable 对象、promise 尝试会有什么结果 ?这篇文章不再专门对此举例
是不是感觉这两个 foo 很像,再来试一下异常处理:
async function foo() {
// ...
throw new Error("error message")
}
foo().catch(err => {
console.log(err); // error message
})
我们发现真的可以,foo() 是一个 Promise。可是这有什么用,我们已经有定义 Promise 的方法了。别着急,我们还有一个伙伴没有介绍呢
await
await
关键字只在 async 函数内有效。在 async 函数体之外使用它,会抛出语法错误 SyntaxError
也就是说 await 必须要在 async 里面,像这样:
async function foo() {
await ...
}
那么 await 具体怎么使用呢 ?来看一下这段代码
我们发现在这段代码中打印 code
,并不会像之前的 Promise 一样返回 undefined 了,而是直接给到我们想要的结果。是不是比之前舒服了很多?!不用操心代码执行顺序的问题,全部同步化。
await 下面的内容就相当于在 promsie 的 then() 方法中一样,会在拿到结果后继续执行
? 可以在 await 后继续发起“链式调用”,而且作为 foo() 的异步函数也不会影响后续代码的执行:
对了,还有一点。在 Promsie 被拒绝或抛出异常时,可直接使用 try/catch 捕获错误原因
function resolveAfter2Seconds(code) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(code);
}, 2000);
});
}
async function foo() {
try {
await resolveAfter2Seconds(500);
} catch (err) {
console.log(err); // 500
}
}
foo();
结语
相对于 Promise,async/await
在处理一般异步代码时确实会更加的直观和简洁,尤其是在处理链式调用时表现的更加优秀。
十分感谢小伙伴们能看到这里,这篇文章相对于前几篇篇幅略小,但不得不承认 async/await 确实很香,所以理解这篇文章很容易,我们更应该在实际开发中多实践才行。