跳到主要内容

async/await 是语法糖,异步的本质还是回调函数

async/await 语法

  • 异步回调容易产生 callback hell(回调地狱)
  • Promise then catch 链式调用,但也是基于回调函数
  • async/await 是同步语法,彻底消灭回调函数,代码演示:
//加载图片
function loadImg(src) {
const p = new Promise((resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`)
reject()
}
img.src = src
})
return p
}
const src1 = 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
const src2 = 'https://box.bdimg.com/static/fisp_static/common/img/searchbox/logo_news_276_88_1f9876a.png'
// !用于解决报错 Uncaught TypeError: "https..." is not a function is not a function
!(async function(){
// 同步的写法
const img1 = await loadImg1()//也可以直接用 loadImg(src1)
console.log(img1.width,img1.height)
const img2 = await loadImg2() //也可以直接用 loadImg(src2)
console.log(img2.width,img2.height)
})()
async function loadImg1(){
const img1 = await loadImg(src1)
return img1
}
async function loadImg2(){
const img2 = await loadImg(src2)
return img2
}

async/await 和 Promise 的关系

  • async/await 是消灭异步回调的终极武器
  • 但和 Promise 并不互斥,反而两者相辅相成
  • 执行 async 函数,返回的是 Promise 对象
async function fn1(){
return 100
// return Promise.resolve(200)
}
const res1 = fn1() // 执行 async 函数,返回 Promise 对象
console.log('res1',res1) // res1 Promise
res1.then(data=>{
console.log('data1',data) // data1 100
})
  • await 相当于 Promise 的 then
async function fn1(){
return 100
// return Promise.resolve(200)
}
!(async function(){
const p1 = Promise.resolve(300)
const data = await p1 // await 相当于 Promise then
console.log('data',data) // data 300
})()
!(async function(){
const data1 = await 400 // 直接返回 400
console.log('data',data1) // data 400
})()
!(async function(){
const data2 = await fn1() // await 相当于 Promise.resolve(100)
console.log('data',data2) // data 100
})()
  • try...catch 可捕获异常,代替了 Promise 的 catch
!(async function () {
const p4 = Promise.reject('err') // rejected状态
try {
const res4 = await p4
console.log('res4', res4) // 不执行
} catch (e) {
console.error('err4',e) //err4 err try…catch 相当于 Promise catch
}
})()
// 没有 try…catch 无法捕获错误
!(async function(){
const p5 = Promise.reject('err1') // rejected状态
const res5 = await p5 // await -> then,下面不会执行
console.log('res5',res5) // 不执行
})()

异步的本质

  • async/await 是消灭异步回调的终极武器
  • JS 还是单线程,还得是有异步,还得是基于 event loop
  • async/await 只是一个语法糖,代码演示:
async function async1() {
console.log('async1 start') // step 2
await async2() //undefined
// await 的后面,都可以看做是 callback 里的内容,即异步
// 类似 event loop,setTimeout(function(){ console.log('async1 end')})
// 或 Promise.resolve().then(()=>{console.log('async1 end')})
console.log('async1 end') // step 5
}
async function async2() {
console.log('async2') // step 3
}
console.log('script start') // step 1
async1()
console.log('script end') // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end

再看一个例子:

async function async1() {
console.log('async1 start') // step 2
await async2()
// 下面都是异步回调 callback 的内容
console.log('async1 end') // step 5
await async3()
// 下面都是异步回调 callback 的内容
console.log('async1 end 2') // step 7
}
async function async2() {
console.log('async2') // step 3
}
async function async3(){
console.log('async3') // step 6
}
console.log('script start') // step 1
async1()
console.log('script end') // step 4
// 同步代码已经执行完(event loop)
// script start
// async1 start
// async2
// script end
// async1 end
// async3
// async1 end 2

补充 for ... of 异步的使用

  • for ... in (以及 forEach for )是常规的同步遍历
  • for ... of 常用于异步的遍历
function muti(num) {
return new Promise(resolve => {
setTimeout(() => {
resolve(num * num)
}, 1000)
})
}
const nums = [1, 2, 3]
nums.forEach(async (i) => { // 1秒后同步执行
const res = await muti(i) // 相当于 Promise 的 then
console.log(res) // 1 4 9
})
!(async function () {
for (let i of nums) { // 1秒执行一个
const res = await muti(i) // 相当于 Promise 的 then
console.log(res) // 1 4 9
}
})()