分类
默认

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
    }
})()