js異步編程終級解決方案 async/await

 

在最新的ES7(ES2017)中提出的前端異步特性:async、await。前端

async、await是什麼

 

async顧名思義是「異步」的意思,async用於聲明一個函數是異步的。而await從字面意思上是「等待」的意思,就是用於等待異步完成。而且await只能在async函數中使用express

一般async、await都是跟隨Promise一塊兒使用的。爲何這麼說呢?由於async返回的都是一個Promise對象同時async適用於任何類型的函數上。這樣await獲得的就是一個Promise對象(若是不是Promise對象的話那async返回的是什麼 就是什麼);promise

await獲得Promise對象以後就等待Promise接下來的resolve或者reject。異步

async、await解決了什麼問題

 

先來看下沒有async/await以前js是如何處理異步操做的:async

傳統的回調地獄式寫法:函數

Promise改進後的寫法:oop

async/await改進後:測試

 

async、await寫法

 

先來看下同步的寫法spa

1 console.log(1); 2 
3 setTimeout(function () { 4   console.log(2); 5 }, 1000); 6 
7 console.log(3);

 下圖是輸出結果:線程

 

 

能夠看到輸出的順序並非咱們代碼中所寫的那樣,下面來看下async、await是如何解決這個問題的

 1 (async function () {  2 
 3   console.log(1);  4 
 5   await new Promise(function (resolve, reject) { 
7
setTimeout(function () { 8 console.log(2); 9 resolve(); 10 }, 1000); 11 }); 12 13 console.log(3); 14 15 }())

 

能夠看到這中寫法的輸出已經符合了咱們的預期,中間還多輸出了一個Promise對象,這個原理能夠用MDN上的官方定義來解釋一下。

先來看下async是如何定義的

When an async function is called, it returns a Promise. When the async function returns a value,
the Promise will be resolved with the returned value. When the async function throws an exception
or some value, the Promise will be rejected with the thrown value.
這裏說了三件事情
  • async函數會返回一個Promise對象;
  • 若是async函數中是return一個值,這個值就是Promise對象中resolve的值;
  • 若是async函數中是throw一個值,這個值就是Promise對象中reject的值;

再來看下await的定義

An async function can contain an await expression, that pauses the execution of the async
function and watis for the passed Promise's resolution, and then resumes the async
function's execution and returns the resolved value.
這裏是說await會暫停當前async函數的執行,等待後面的promise的計算結果後再繼續當前的async函數。
 
看到這裏就明白了,首先, await只能在async裏面;而後, await後面要跟一個promise對象;

常規的promise對象會被js先暫存到 eventloop(事件隊列)中,由於js是單線程執行的,等 執行棧空了以後,纔會將事件隊列中的事件取出放入執行棧中執行。
 
上述代碼中先是將整段代碼改形成了一個async(async能夠用於任何函數)函數,而後又將setTimeOut改形成了一個Promise對象。
 
這裏我作了一下實驗,若是改造後的Promise對象不加resolve()會是什麼狀況:
 1 (async function () {  2 
 3   console.log(1);  4 
 5   await new Promise(resolve => {  6     setTimeout(() => {  7       console.log(2);  8     }, 1000);  9  }); 10   console.log(3); 11 }())

能夠看到結果是這個樣子,也就是說若是await後面等待的Promise對象如何不進行resolve() 的話,async函數就沒法繼續(至少我如今是這樣理解的)。那若是await後面等的不是Promise對象呢,async還能繼續走下去嗎。

這裏我寫了個簡單的代碼測試了一下:

 1 function getSomething() {  2     console.log("something");  3 }  4 
 5 async function testAsync() {  6     console.log("hello async");  7 }  8 
 9 async function test() { 10  await getSomething(); 11  await testAsync(); 12 } 13 
14 test();

顯而易見,若是await後面等是普通函數的話,那就會照常執行,和不加await是同樣的。


總結一下,async/await就是爲了解決異步回調而生的,它可讓你的異步代碼寫的像同步的同樣具備良好的可讀性,以上就是本人對async/await的一些理解,不足之處請指正,謝謝。

相關文章
相關標籤/搜索