JavaScript中的Promise和async/await


一、同步与异步有何不同:

1.JavaScript是单线程的语言

2.异步不会阻塞代码执行

3.同步会阻塞代码执行

 

二、异步的应用场景:需要等待的情况

1.网络请求,如ajax图片加载

2.定时任务,如setTimeout

 

三、promise的基本使用:

1.通过串行的方式解决了回调地狱的问题

2.手写promise加载图片:

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(err) } img.src = src } ) return p } const url1 = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg' const url2 = 'https://img3.mukewang.com/5a9fc8070001a82402060220-100-100.jpg' loadImg(url1).then(img1 => { console.log(img1.width) return img1 // 普通对象
}).then(img1 => { console.log(img1.height) return loadImg(url2) // promise 实例
}).then(img2 => { console.log(img2.width) return img2 }).then(img2 => { console.log(img2.height) }).catch(ex => console.error(ex))

 

四、promise的状态:

1.三种状态:

(1)pending(过程中)、resolved(解决了,也叫fulfilled)、rejected(失败了)

(2)pending => resolved 或 pending => rejecte

(3)变化不可逆

// 刚定义时,状态默认为 pending
const p1 = new Promise((resolve, reject) => { }) // 执行 resolve() 后,状态变成 resolved
const p2 = new Promise((resolve, reject) => { setTimeout(() => { resolve() }) }) // 执行 reject() 后,状态变成 rejected
const p3 = new Promise((resolve, reject) => { setTimeout(() => { reject() }) })

 

2.状态的表现和变化:

(1)pending状态,不会触发then和catch

(2)resolved状态,会触发后续的then回调函数

(3)rejected状态,会触发后续的catch回调函数

// 直接返回一个 resolved 状态
Promise.resolve(100) // 直接返回一个 rejected 状态
Promise.reject('some error')

 

3.then和catch对状态的影响:

(1)then正常情况下返回resolved,里面有报错则返回rejected

(2)catch正常情况下返回resolved,里面有报错则返回rejected

// then() 一般正常返回 resolved 状态的 promise
Promise.resolve().then(() => { return 100 }) // then() 里抛出错误,会返回 rejected 状态的 promise
Promise.resolve().then(() => { throw new Error('err') }) // catch() 不抛出错误,会返回 resolved 状态的 promise
Promise.reject().catch(() => { console.error('catch some error') }) // catch() 抛出错误,会返回 rejected 状态的 promise
Promise.reject().catch(() => { console.error('catch some error') throw new Error('err') })

 

五、promise题目:

// 第一题,答案是1、3
Promise.resolve().then(() => { console.log(1) }).catch(() => { console.log(2) }).then(() => { console.log(3) }) // 第二题,答案是1、2、3
Promise.resolve().then(() => { // 返回 rejected 状态的 promise
    console.log(1) throw new Error('erro1') }).catch(() => { // 返回 resolved 状态的 promise
    console.log(2) }).then(() => { console.log(3) }) // 第三题,答案是1、2
Promise.resolve().then(() => { // 返回 rejected 状态的 promise
    console.log(1) throw new Error('erro1') }).catch(() => { // 返回 resolved 状态的 promise
    console.log(2) }).catch(() => { console.log(3) })

 

六、async/await:

1.背景:

(1)异步回调的callback hell

(2)Promise then catch链式调用,但也是基于回调函数

(3)async/await是同步语法,消灭回调函数

 

2.基本使用:

function loadImg(src) { const promise = new Promise((resolve, reject) => { const img = document.createElement('img') img.onload = () => { resolve(img) } img.onerror = () => { reject(new Error(`图片加载失败 ${src}`)) } img.src = src }) return promise } async function loadImg1() { const src1 = 'http://www.imooc.com/static/img/index/logo_new.png' const img1 = await loadImg(src1) return img1 } async function loadImg2() { const src2 = 'https://avatars3.githubusercontent.com/u/9583120' const img2 = await loadImg(src2) return img2 } (async function () { // 注意:await 必须放在 async 函数中,否则会报错
    try { // 加载第一张图片
        const img1 = await loadImg1() console.log(img1) // 加载第二张图片
        const img2 = await loadImg2() console.log(img2) } catch (ex) { console.error(ex) } })()

 

3.async/await和Promise的关系:async/await可以消灭异步回调,但它和Promise并不互斥,两者相辅相成

(1)执行async函数,返回的是Promise对象(如果函数内没返回Promise对象,或者直接返回一个数值,则自动封装成Promise对象)

(2)await相当于Promise的then

  1)基本原则:
    await 后面跟 Promise 对象:会阻断后续代码,等待状态变为 resolved ,才获取结果并继续执行
    await 后续跟非 Promise 对象:会直接返回
  2)详细使用:

    A.可以声明一个变量接收函数的返回值:

      

      这里的data2接收了fn1的返回值

    B.await后面可以跟Promise对象、数值、一个async函数的返回值(async函数的返回值相当于Promise对象):

      

    C.await后面跟rejected的Promise对象,则不会执行,所以要用try...catch捕获:

!(async function () { const p3 = Promise.reject('some err') const res = await p3 console.log(res) // 不会执行,因为await相当于then
})()

    D.await是同步写法,但本质还是异步调用。只要遇到了await,后面的代码都相当于放在 callback 里: 

async function async1 () { console.log('async1 start') await async2() console.log('async1 end') // 关键在这一步,它相当于放在 callback 中,最后执行
} async function async2 () { console.log('async2') } console.log('script start') async1() console.log('script end')

      

 

(3)用try...catch可捕获异常,代替了Promise的catch

!(async function () { const p4 = Promise.reject('some err') try { const res = await p4 console.log(res) } catch (ex) { console.error(ex) } })()

  用try...catch捕获异常使语法更加标准化(像其他语言一样)

 

4.总结:

(1)async函数封装了Promise

(2)await相当于Promise的then,处理Promise成功的情况

(3)要用try...catch处理Promise失败的情况

 

七、async/await的本质:

1.async/await可以消灭异步回调

2.JavaScript还是单线程,还是得有异步,还是得基于事件循环(event loop)

3.async/await只是语法糖,只是从语法层面解决了异步回调

 

八、async/await题目:

1.第一题,答案:a是一个promise对象,b是100,因为async函数返回一个promise,而await相当于promise里面的then

 

2.第二题,答案:先打印start,然后a是100,b是200,执行到打印c会报错,然后后面的代码都不会执行了,因为await相当于then,只执行resolved,而这里是rejected,需要try..catch来执行

 

3.第三题,答案:依次打印script start、async1 start、async2、promise1、script end、async1 end、promise2、setTimeout,原因:

(1)setTimeout是宏任务

(2)await后面的都作为回调内容,是微任务

(3)初始化promise时,传入的函数会立刻被执行

(4)then后面的回调是微任务

  

 

4.第四题(请使用Promise.all并行请求数据):

const getInfo = async(qq, callback) => { let baseInfo let payInfo try { let uidData = await axios.get('http://test.com/getUid', { params: { qq } }) if(uidData.ret === 0) { let uid = uidData.uid let [baseInfoData, payInfoData] = await Promise.all([ axios.get('http://test.com/getBaseInfo', { params: { uid } }), axios.get('http://test.com/getPayInfo', { params: { uid } }) ]) if(baseInfoData.ret === 0) { baseInfo = baseInfoData.info } else { baseInfo = {} } if(payInfoData.ret === 0) { payInfo = payInfoData.info } else { payInfo = {} } callback(Object.assign({}, baseInfo, payInfo)) } else { callback({}) } } catch(err) { throwError(err) } } getInfo(123456, function(data) { console.log(data) })

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM