es7中的async、await使用方法示例詳解

async、await 是es7裡面的新語法,它的作用就是 async 用於申明一個 function 是異步的,而 await 用於等待一個異步方法執行完成。它可以很好的替代promise 中的then。async 函數返回一個 Promise 對象,可以使用then 方法添加回調函數。當函數執行的時候,一旦遇到await 就會先返回,等到異步操作完成,再接著執行函數體內後面的語句。

一、前言

回調是JavaScript在es5之前處理異步方法的常用方式,當異步調用又調用瞭異步方法時,前端的小夥伴們應該都遇到過這種場景吧,回調方式的寫法讓人看得頭皮發麻,代碼的可讀性非常差

ES2015中引入Promise, 目的就是為瞭解決著名的回調地獄,但是它自己引入瞭語法復雜性。示例如下:

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}
 
takeLongTime().then(v => {
    console.log("got", v);
});

ES2017增加瞭異步函數async/await,提高瞭代碼可讀性,讓調用異步方法像同步一樣簡單。示例如下:

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}
 
async function test() {
    const v = await takeLongTime();
    console.log(v);
}
 
test();

async/await使代碼看起來像是同步的,但它在後臺是異步和非阻塞的。可以理解 await 後面的語句相當於放到瞭 new Promise 中,下一行及之後的語句相當於放在 Promise.then 中。 async 會將其後的函數(函數表達式或 Lambda)的返回值封裝成一個 Promise 對象,而 await 會等待這個 Promise 完成,並將其 resolve 的結果返回出來。

二、async 和 await 的基礎使用

async/awiat 的使用規則:

    async 返回的是一個 Promise 成功的對象,await 就是等待這個 promise 的返回結果後,再繼續執行
    await 等待的是一個 Promise 對象,後面必須跟一個 Promise 對象,但是不必寫 then (),直接就可以得到返回值

但註意,await 所等待的 promise 對象,他的最終狀態一定是 resolve 的(當然也可以不是 resolve ,隻不過不會執行後面的代碼罷瞭),否則不會執行await 後面的代碼,也就是不會去執行所謂的 then() ;

三、async \ await使用場景

//將請求改造成一個通用函數
function request(options) {
    //.....
    return new Promise(....); //使用Promise執行請求,並返回Promise對象
}
//於是我們就可以來發送請求瞭
request("ajaxA")
.then((data)=>{
   //處理data
   return request("ajaxB")
})
.then((data)=>{
   //處理data
   return request("ajaxC")
})
.then((data)=>{
   //處理data
   return request("ajaxD")
})

如果能像使用同步代碼那樣, 使用Promise就好瞭。於是, async \ await出現瞭

function request(options) {
    //.....
    return new Promise(....); //使用Promise執行請求,並返回Promise對象
}
//wait這個單詞是等待的意思
async function load(){
    await request("ajaxA");  //那麼這裡就是在等待ajaxA請求的完成
    await request("ajaxB");
    await request("ajaxC");
    await request("ajaxD");
}

await關鍵字使用的要求非常簡單, 後面調用的函數要返回一個Promise對象。load()這個函數已經不再是普通函數, 它出現瞭await這樣"阻塞式"的操作 因此async關鍵字在這是不能省略的。與之前長長的then鏈和then方法裡的回調函數相比,這樣的寫法看起來像是同步寫法並且更加清爽,更加符合編程習慣。

四、await返回打印測試

await後面的promise狀態不是resolve的輸出結果

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1');
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

/* await後面的promise狀態不是resolve的輸出結果
"srcipt start"
"async1 start"
"promise1"
"srcipt end"
*/

這裡我們可以看到:在 async1 中 await 後面的 Promise 是沒有返回值的,也就是它的狀態始終是 pending 狀態,所以在 await 之後的內容是不會執行的,包括 async1 後面的 .then。

await後面的promise狀態是resolve的輸出結果

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1');
    resolve()
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

/*await後面的promise狀態是resolve的輸出結果
"srcipt start"
"async1 start"
"promise1"
"srcipt end"
"async1 success"
"async1 end"
*/

五、總結

解決函數回調經歷瞭幾個階段, Promise 對象, Generator 函數到async函數。async函數目前是解決函數回調的最佳方案。很多語言目前都實現瞭async,包括Python ,java spring,go等。

async 函數返回一個 Promise 對象,當函數執行的時候,一旦遇到 await 就會先返回,等到觸發的異步操作完成,再接著執行函數體內後面的語句。

到此這篇關於es7中的async、await使用方法示例詳解的文章就介紹到這瞭,更多相關async、await使用示例內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: