Promise是一個建構式,口語上就好像是我給你XXX的承諾,它是ES6提供用來做非同步處理及制作時間延遲處理的方法,比較常用來處理AJAX的行為。
既然Promise是建構式,那就是用new的方式來建立一個實體使用它,這邊先舉一個簡單的例子,如下圖所示Promise它會回傳2個引數的函式,一個是resolve,一個是reject,這兩個引數的函式分別需要用then及catch去接收
Resolve : 就字面上的意思,可以理解為是用來接收成功後的資料,然後用then去接
Reject : 它跟Resolve一樣可以帶資料進去,不過它是用catch去接,從字面上也不難理解它應該是會用在接收失敗後的資訊
另外要注意的是promise它無法同時間回傳resolve和reject,也就是說javascript在收到其中一個時它就會回傳出去了,因此我們就可以做如下的延伸應用
1. 把Promise封裝在函式裡 : 在一般的情況下,為了在運用上比較有彈性(可以帶參數),會透過函式轉為Promise的方式來使用,如下圖所示
2. 透過Promise的鏈接技巧來處理非同步的問題 : 非同步函式中除了setTimeout()、setInterval()外,最常使用的就是抓取後端資料的函式套件,如ajax、axios、原生的new XMLHTTRequest()、fetch…等,一般在運用上我們可能會希望先向後端抓到資料後,再繼續執行某些程式,因此就可以用Promise的鍵接技巧來達到這樣的目的,如下圖的解說,透過return promise()、then的方式,可以用來確保程式的執行流程
這裡另外提一下,像這種return、then的串接方式,其實就是平常我們在用的axios.then的方式,先拿到後端的某個資料後,再用這個資料帶進我們某個函式裡,如下圖所示,假設希望用axios去抓同資料每次都是一樣時,那就可以用到return、then的串接方式來做
3. 使用Promise.all一次處理多個非同步的程序: 由於承第二點雖然可以用return、then的方式來一步步的串接資料,但如果今天是同時處理多個非同步的API時,若是希望這多個非同步API同時處理完後再來進行下一個動作時,我們就可以用Promise.all 的方式來處理,如下圖所示
這邊再舉一個特效的例子,如下圖所示,我希望網頁載入後,先移動文字區塊後再移動按鈕區塊
Promise.all 常用來搭配fetch或axios來封裝並利用取得的資料,如下圖所示,用Promise.all封裝axios來取得資料後,再用then個別去處理對應的資料
4. 搭配Async / Await來使用 : 一樣承如第二點,雖然Promise可以透過reurn、then的方式來進行非同步的串接,但如果今天return、then的串接過多,會顯得程式碼有點冗長,因此就可以用async / await來精簡程式碼,如下圖所示,用async 把Promise的程式封裝起來後,就可以用await去執行 Promise的函式來達到非同步程式的控制
另外async/await 也有提供像Promise的then / catch功能一樣,可以判斷接收resolve或reject的資料,如下圖所示,在async的封裝函式裡放入try / catch,即可接收Promise回傳的resolve或reject的資料
這邊再舉一個實務上比較常見搭配axio的async / await的做法,其實axios、fetch…等抓取後端資料的的底層其實就是promise,所以也可以跟async / await一起搭配使用(也是實務上比較常用的搭配方法),如下圖所示,本來是用then去接資料,改成用async / await的方式也是可以