1. 程式人生 > >ES7 非同步函式 (async await)

ES7 非同步函式 (async await)

1.先說說Promise物件

Promise是ES6中處理非同步操作的一個新方式,Promise物件有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗),寫法如下:

//1)建立promise物件,建立後立刻執行
//接收一個函式作為引數,resolve、reject是Promise狀態發生變化時執行的函式,這裡由js引擎渲染出,不需要手動定義。
var promise = new Promise(function(resolve,reject){
    setTimeout(()=>{
        let num = parseInt(Math.random()*10
) if(num%2){ resolve(0) }else{ reject(1) } },500)
}) //2)狀態改變時的呼叫 promise.then(suc=>{ //執行上面的resolve() console.log(`奇數;${suc}`) },err=>{ //執行上面的reject() console.log(`偶數;${err}`) })

2.async function

async函式是ES7的內容,async函式可以看作是將非同步操作包裝成的一個 Promise 物件,而await命令就是內部then命令的語法糖,語法非常的簡單明瞭。
await 命令後面是一個promise物件,或者是其他非同步程序。await 表示式會暫停當前 async function 的執行,等待 Promise 處理完成。如果Promise 正常處理(fulfilled),其處理結果作為 await 表示式的值,繼續執行 async function;如果 Promise 處理異常,則異常值被丟擲,整個函式停止執行
//定義一個非同步函式
async getData(i){
    let res;
    try(){
        //await 暫停當前函式的執行,直到非同步程序處理完成
        res = await axios.get(`../../static/data${i}.json`)
    }catch(e){
        res = e
    }
    return res
}

async函式返回一個promise物件,函式內部return的值可以作為then方法回撥函式的引數。

getData(0).then(res=>{
    console.log(res)
}
)

3.併發問題

await關鍵字會暫停函式的執行,但不會阻塞程序

下面這種寫法,三個請求依次觸發

async function getNum_1() {
    for(let i = 0; i < 3; i++){
        console.log(`%c start${i}`, "color:green")
        //暫停執行,等待結果
        let res = await axios.get(`../../static/data${i}.json`)
        //獲得結果,處理結果 並 進入下一次迴圈
        console.log(res.data.msg)
    }
}

正確的寫法是這樣:

function getNum_2(){
    for(let i=0; i<3; i++){
        //迴圈呼叫上文中的async函式,多個非同步函式併發,不會阻塞程序
        this.getNum(i) 
    }
}

或者使用Promise物件的all方法

//1)使用map方法建立promise物件陣列
let promises = [0,1,2].map((i)=>{
    return this.getNum(i) // 執行async函式,返回promise物件
})
//2)處理非同步結果
Promise.all(promises).then((res)=>{ 
    //所有非同步方法完成後呼叫
    console.log('done')
})