js的異步回調之async/await

最近在學習NodeJS框架koa V2,koa2的API很簡單,基於ES7 async/await實現異步代碼。不少人認爲async/await是解決異步終極解決方案,那咱們就研究下async/await。
前端業務邏輯愈來愈複雜,每每幾個 AJAX 請求之間互有依賴,有些請求依賴前面請求的數據,有些請求須要並行進行。咱們用ajax來作個例子,根據查找一個省份中的第一個市的區縣。前端

$.get('/url/city',[province:'河北省'],function (result1){
    console.log(result1);
    $.get('/url/county',[city:result1[1]],function (result2){
        console.log(result2);
    })
})

這個是用回調函數執行的異步操做,大量的異步操做就有大量的回調函數,如今咱們是嵌套來三層,假如咱們嵌套了四層五層更多層,這個時候使用回調函數來寫代碼每每會致使代碼難以閱讀,就會造成了回調地獄Callback hell。
如今咱們用比較優雅一點的,看起來像同步實則異步的async/await 重構一下代碼。ajax

var requestUrl=(url,args)=>{
     return new Promise(function(resolve,reject){
        $.get(url,args,(result)=> {
             try {
                  resolve(JSON.parse(result));
             }catch(e){
                  reject(e);
             }    
         }) 
     })
    
}
async function getCounty(province){
    try{
        let result1=await requestUrl('/url/city',{provinces:province});
        console.log(result1);
    }catch(e){
        console.log(e);
    }
    try{
        let result2=await requestUrl('/url/county',{city:result1[1]});
        console.log(result2);
    }catch(e){
        console.log(e);
    }
};
getCounty('河北省');

首先咱們定義了一個requestUrl函數,這個函數返回一個Promise對象resolve,並拿到結果,當即執行函數定義時使用了關鍵字async,在函數體中配合使用了await,執行第一個await會返回‘/url/province’的執行數據全部河北省的市,執行第二個await,返回根據第一個市裏面的區縣。promise

如今咱們瞭解一下async/await的用法;babel

async關鍵字表示這個是一個異步函數,await只能使用在這個函數裏面,若是是在普通函數就會報錯;
await的做用是獲取一個promise對象,獲取返回值以前await後面的語句是沒法繼續執行的。假如await返回的不是一個promise對象,是其餘的任何返回值,await後面的語句會當即執行。框架

ajax比較容易看出call hell問題,如今咱們弄個簡單的例子,能夠在babel中執行一下。koa

var sleep = function (time) {
        setTimeout(function () {
            console.log('test');
        }, time);
};
var start = async function () {
    console.log('start');
    await sleep(3000);
    console.log('end');
};

start();
這個是沒有返回promise對象的例子,執行start()後,先輸出’start‘,而後'end',三秒鐘後輸出'test';異步

var sleep = function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('test');
            console.log('test');
        }, time);
    })
};
async function start() {
    console.log('start');
    let result = await sleep(8000);
    console.log('end');
};
start();

這個是返回promise對象,它先輸出‘start’,而後是等待三秒輸出‘test’,最後輸出‘end’;

在學習過程當中,我被一句話給誤導了,‘看起來像同步實則異步的async/await’,就走到了一個死衚衕裏,await關鍵字聲明一個異步函數,可是await阻止了await後面語句執行,只有await等到了一個返回值纔會繼續執行,這不就是同步執行了嗎?完全的懵了,後來恍然大悟,async聲明start()爲異步函數,假如再有一個start2(),它們並行執行的,在babel裏面測試以下圖:
clipboard.png
因此異步的點在這。而await關鍵字只有獲得返回值後才繼續執行,不就是同步麼。搞定!!!
async函數返回一個Promise對象,可使用then()添加回調,catch()捕獲異常,當咱們也能夠用try/catch,就是async

相關文章
相關標籤/搜索