JavaScript 基础
函数进阶
深入数据和类型
运算符
浏览器存储
Document
Web API
事件
错误处理
异步编程
网络请求
模块
练习
实例
工具与规范
async、await
async 与 await 是两个关键字,能让我们用同步的写法来写异步的程序。
async
async
关键字用于函数前面,它能使用函数返回的的值变成一个 promise:
$$jsdemo$$
$$edit$$
async function func() {
return "三眼鸭"
}
let promise = func()
console.log(promise)
它与以下的代码是等价的:
$$jsdemo$$
$$edit$$
let promise = new Promise(function (resolve, reject) {
resolve("三眼鸭")
})
console.log(promise)
单单是这样并不能体现 async 的作用, async 需要搭配 await 使用才能起到效果。
await
await
关键字表示等待 promise 执行完成并得到执行结果, await
只能在 async
函数中使用。
let promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("三眼鸭")
}, 3000)
})
async function func() {
let result = await promise
alert(result) // 三眼鸭,等待执行完成
alert("执行完毕") // 执行完毕
}
func()
await
并不意味着会阻塞 JavaScript 的主线程的执行, 它阻塞的只是 async
函数的执行。
$$jsdemo$$
$$edit$$
let promise = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("三眼鸭")
}, 3000)
})
async function func() {
let result = await promise
alert(result) // 三眼鸭,等待执行完成
alert("执行完毕") // 执行完毕
}
func()
alert("END") // 最先执行
async、await 的好处
async
与 await
最大的好处就是让我们用同步的思维去写异步的程序。
假设我们有以下代码,要下载一个文件,这个文件的下载链接包含在 A 文件当中,而 A 文件的下载链接包含在 B 中, B 又包含在 C 中。
那么我们要依次下载 C → B → A → 最终文件,那么代码就得写成以下这样:
$$jsdemo$$
$$edit$$
function download() {
// 这个下载花费 2 秒钟
return new Promise((resolve, reject) => {
let file = "我是文件哦"
setTimeout(() => resolve(file), 2000)
})
}
console.log("开始执行了~")
console.log("先去下个文件~")
// 下载好了通知我就行,不等你了
download().then((file) => {
console.log("下载 C 完成")
console.log("拿到 B 的链接")
download().then((file) => {
console.log("下载 B 完成")
console.log("拿到 A 的链接")
download().then((file) => {
console.log("下载 A 完成")
console.log("拿到 最终文件 的链接")
download().then((file) => {
console.log("下载 最终文件 完成")
})
})
})
})
console.log("做其他事情去了~")
我们会陷入回调地狱中,回调越写越多,代码执行顺序越来越混乱。
那么就可以使用 asnyc
、 await
改写我们的程序了:
$$jsdemo$$
$$edit$$
function download() {
// 这个下载花费 2 秒钟
return new Promise((resolve, reject) => {
let file = "我是文件哦"
setTimeout(() => resolve(file), 5000)
})
}
async function getFile() {
let file = await download()
console.log("下载 C 完成")
console.log("拿到 B 的链接")
file = await download()
console.log("下载 B 完成")
console.log("拿到 A 的链接")
file = await download()
console.log("下载 A 完成")
console.log("拿到 最终文件 的链接")
file = await download()
console.log("下载 A 完成")
console.log("下载 最终文件 完成")
}
console.log("开始执行了~")
console.log("先去下个文件~")
getFile()
console.log("做其他事情去了~")
错误处理
await
返回的是 resolve
的结果,如果是 reject
则会抛出一个错误,我们需要处理这个错误的话则需要使用 try ... catch
。
$$jsdemo$$
$$edit$$
let promise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("三眼鸭"))
}, 3000)
})
async function func() {
try {
let result = await promise // throw new Error("三眼鸭")
alert(result)
alert("执行完毕")
} catch (error) {
alert(error) // Error: 三眼鸭
}
}
func()