【面试题】async/await

1. async/await基本语法

  JS是单线程语言,只能同时做一件事。当遇到等待的情况时,例如网络请求、定时任务,程序不能卡住。所以需要异步来解决JS单线程等待的问题,异步通过回调callback函数的形式实现。但是异步回调存在callbakc hell的问题,可以通过Promise的then,catch链式调用来解决,但是这种解决方案仍然是基于回调函数的。
  async/await是同步语法,能以不使用回调函数的方式来实现异步。await被async包裹,await后面可以追加Promise对象,也可以追加async函数。

// 加载图片并打印图片的高和宽
function loadImg(src) {
    const p = new Promise((resolve, reject)=>{
        const img = document.createElement('img')
        img.onload = ()=>{
            resolve(img)
        }
        img.onerror = ()=>{
            reject(new Error(`图片加载失败 ${src}`))
        }
        img.src = src
    })
    return p;
}

const url1 = 'https://profile-avatar.csdnimg.cn/fb030a9b9de24f4ba6dd8cd6c094ffcf_zx1041561837.jpg!1'
const url2 = 'https://img-home.csdnimg.cn/images/20201124032511.png'

!(async function(){
    const img1 = await loadImg(url1)
    console.log(img1.height, img1.width)   // 打印图片的高,宽

    const img2 = await loadImg(url2)
    console.log(img2.height, img2.width)
})()

2. async/await和Promise的关系

  • 执行async函数,返回的是一个Promise对象。如果直接返回一个值,那么会把这个值封装成一个Promise对象。
async function fn1(){
    return 100    // 相当于 return Promise.resolve(100)
}

const res1 = fn1()
console.log('res1', res1)  // Promise对象

res1.then(data=>{
    console.log('data', data)   // 100
})
async function fn1(){
    return Promise.resolve(200)
}

const res1 = fn1()
console.log('res1', res1)  // Promise对象

res1.then(data=>{
    console.log('data', data)   // 200
})
  • await相当于Promise的then
!(async function(){
    const p1 = Promise.resolve(300)
    const data = await p1   // await 相当于 Promise的then
    console.log('data', data)    // 300
})()
!(async function(){
	// await后面直接跟一个值,那么会自动封装成Promise对象 await Promise.resolve(400)
    const data = await 400   
    console.log('data', data)    // 400
})()
async function fn1(){
    return Promise.resolve(200)
}

!(async function(){
    const data = await fn1()  
    console.log('data', data)  // 200
})()
  • try…catch代替Promise的catch,用于捕获异常

Promise的状态为rejected,那么await不会执行,这个时候就要用try…catch,它相当于Promise中的catch。

!(async function(){
    const p = Promise.reject('err1')   // rejected状态
    const res = await p    // await相当于then
    console.log(res)  // 不会执行
})

解决方法:

!(async function(){
    const p = Promise.reject('err1')   // rejected状态
    try{
        const res = await p
        console.log(res)
    }catch(ex){
        console.error(ex)    // try...catch 相当于 Promise的catch
    }
})()

3. 异步的本质

async/await是语法糖,异步的本质还是回调函数,代码执行规则依然按照Event Loop进行。

async function async1(){
    console.log('async1 start') // 顺序2
    // await 的后面,都可以看作是callback里的内容,即异步
    await async2()
    // Promise.resolve.then(()=>{console.log('async1 end'}) 
    console.log('async1 end')  // 顺序5
}

async function async2(){
    console.log('async2')  // 顺序3
}

console.log('script start')  // 顺序1
async1()
console.log('script end')  // 顺序4

【面试题】async/await_第1张图片

async function async1() {
    console.log('async1 start')   // 顺序2
    await async2()
    console.log('async1 end')   // 顺序5
    await async3()
    console.log('async1 end2')   // 顺序7
}

async function async2() {
    console.log('async2')  // 顺序3
}

async function async3(){
    console.log('async3')  // 顺序6
}

console.log('script start')   // 顺序1
async1()
console.log('script end')  // 顺序4

【面试题】async/await_第2张图片

你可能感兴趣的:(面试题,前端,javascript)