ES6之async await

含義

  • 內置執行器
    • Generator函數的執行必須靠執行器,因此纔有了co模塊,而async函數自帶執行器。也就是說,async函數的執行,與普通函數如出一轍,只要一行fn()
  • 更好的語義
    • async和await,比起星號和yield,語義更清除了。async表示函數裏又異步操做,await表示緊跟在後面的表達式須要等待結果。
  • 更廣的適用性
    • co模塊規定,yield命令後面只能時Thunk函數或Promise對象,而async函數的await命令後面,可不是Promise對象和原始類型的值(數值、字符串和布爾值,但這時會自動轉成當即resolved 的Promise對象)
  • 返回值時Promise
    • async函數的返回值時Promise對象,這比Generator函數的返回值是Iterator對象方便多了。你能夠用then方法制定下一步操做。

進一步說,async函數徹底能夠看做多個異步操做,包裝成的一個Promise對象,而await命令就是then方法的語法糖promise

基本用法

async函數返回一個Promise對象,可使用then方法添加回調函數。當函數執行的時候,一旦遇到await就會先返回,等到異步操做完成,在接着執行函數體後面的語句異步

async function fn(){
        console.log(4)
        let f1 = await Promise.resolve(1)
        console.log(f1) // 1
        let f2 = await Promise.resolve(2)
        return f2
    }
    fn().then(res=>{
        console.log(res) // 2
    })
    console.log(3)
    // 4  3  1  2

上面代碼中,函數前面的async關鍵字,表示函數內部有異步操做。調用該函數時,會當即返回一個Promise對象。async

function timeout(ms){
        return new Promise((resolve)=>{
            setTimeout(resolve,ms)
        })
    }
    async function fn(value,ms){
        await timeout(ms)
        console.log(value)
    }
    fn('haha',3000)

上面代碼會在3秒後輸出haha函數

async函數有多種使用形式。this

// 函數聲明
    async function fn(){}
    // 函數表達式
    let fn1 = async function(){}
    // 對象的方法
    let obj = {async foo(){}}
    obj.foo().then(()=>console.log(111)) // 111
    // class 的方法
    class fn2{
        constructor(name){
            this.name = name;
        }
        async getName(){
            return this.name
        }
    }
    let name = new fn2('小明');
    name.getName().then(res=>console.log(res)) // 小明

語法

async函數返回一個Pormise對象。
async函數內部return語句返回的值,會成爲then方法回調函數的參數code

let fn = async function(){
        return 111
    }
    fn().then(res=>{console.log(res)}) // 111

上面代碼,函數fn返回的值,會被then放回回調函數接收到orm

async內部拋出錯誤,會致使返回的Promise對象變爲reject狀態。拋出的錯誤對象會被catch方法回調函數接收到。對象

let fn = async function(){
        throw new Error('出錯了')
    }
    fn().catch(error=>{
        console.log(error); // Error: 出錯了
    })
Promise對象的狀態變化

async函數返回的Promise對象,碧璽等到內部全部await命令後面的Promise對象執行完,纔會發生狀態改變,除非遇到return語句或者拋出錯誤。也就是說,只有asunc函數內部的異步操做執行完,纔會執行then方法指定的回調函數。字符串

let fn = async function(){
        await new Promise((resolve)=>{
            setTimeout(resolve,3000)
        })
        await new Promise((resolve)=>{
            setTimeout(resolve,3000)
        })
        return 1
    }
    fn().then(res=>{
        console.log(res);
    })

上面代碼,then回調函數會在6秒以後輸出resget

await

正常狀況下,await命令後面是一個Promise對象,返回該對象的結果。若是不是Promise對象,就直接返回對應的值

let fn = async function(){
        // 等同於
        // return 1
        return await 1
    }
    fn().then(res=>{
        console.log(res); // 1
    })

上面代碼中,await命令的參數是數值1,這是等同於return 1

let fn = async ()=>{
        await Promise.reject('出錯了')
    }
    fn().catch(error=>{console.log(error)}) // 出錯了

注意:上面代碼中,await語句前面沒有return,可是reject方法的參數依然傳入了catch方法的回調函數。這裏若是在await前面加上return,效果是同樣的

注意:任何一個await語句後面的Promise對象變爲reject,那麼整個async函數都會中斷執行

有時,咱們但願即便前一個異步操做失敗,也不要中斷後面的異步操做。這時能夠將第一個await放在try...catch結構裏面,這樣無論這個異步操做是否成功,第二個await都會執行

let fn = async ()=>{
        try{
            await Promise.reject('出錯了')
        }catch(error){
            console.log(error) 
        }
        return 1
    }
    fn().then(res=>console.log(res)) // 1

另外一種寫法

let fn = async ()=>{
        await Promise.reject('出錯了').catch(error=>{
            console.log(error) 
        })
        return 1
    }
    fn().then(res=>console.log(res)) // 1

錯誤處理

若是await後面的異步操做出錯,那麼等同於async函數返回的 Promise 對象被reject。

let fn = async ()=>{
        await Promise.reject('出錯了')
        return 1
    }
    fn()
    .then(res=>console.log(res))
    .catch(error=>{
        console.log(error) // 出錯了
    })

上面代碼中,函數fn執行後,await後面的Promise對象拋出了一個錯誤對象,致使catca方法的回調函數被調用。

防止出錯的方法,也是將其放在try...catch代碼塊中

let fn = async ()=>{
        try{
            await Promise.reject('出錯了')
        }catch(error){
            console.log(error);
        }
        return 1
    }
    fn()
    .then(res=>console.log(res)) // 1

若是有多個await命令,能夠統一放在try...catch

相關文章
相關標籤/搜索