Promise入門之基本用法

Promise入門之基本用法

背景

在咱們使用異步函數好比ajax進行編寫代碼,若是咱們須要不少個ajax請求不一樣的接口,而下一個接口須要依賴上一個接口的返回值,這樣,咱們的代碼則須要在各類回調函數中嵌套,這樣一層一層地下去,就造成了回調地獄。
可是promise的出現則不須要嵌套就能解決這個問題。什麼是promise?promise本質實際上是一個對象,用於傳遞異步操做的信息。而且promise這個對象提供了相對應的API,知足咱們的需求開發。ajax

建立promise對象

let pro = new Promise(function(resolve, reject){
    // 異步處理邏輯
    // 處理完畢以後調用resolve或者reject
})

promise對象跟其餘普通對象的建立方法同樣,只須要new一個新的對象便可,接受一個函數做爲參數,而且該函數中的參數分別爲兩個回調函數,用於進行不一樣的邏輯處理。
在定完一個promise對象以後,咱們能夠經過調用then方法來執行其對應的邏輯數組

pro.then(function(res){
    // 若是promise對象調用了resolve方法,則進入該函數邏輯
}, function(err){
    // 若是promise對象調用了reject方法,則進入該函數邏輯
})

promise的狀態

promise的實例主要有如下三種狀態:
①pending: 處理中
②fulfilled: 成功
③rejected: 失敗promise

pending狀態的promise能夠轉化爲fulfilled狀態或者rejected狀態,該轉化不可逆且只能轉化一次。同時,fulfilled狀態和rejected狀態只能由pending狀態轉化,相互不能轉化。如圖異步

clipboard.png

pending狀態下的promise在處理完業務邏輯,且能正常退出時即可以執行resolve方法,從而進入fulfilled狀態;
若pending狀態下的promise在處理業務邏輯的過程當中出現異常錯誤,或者主動調用reject方法,則進入rejected狀態。async

let pro = new Promise(function(resolve, reject){
    if(// 邏輯處理完畢且能正常退出){
        resolve()
    }
    else{
        // 異常錯誤拋出
        reject()
    }
})

pro.then(function(res){
    // 若是promise對象調用了resolve方法,則進入該函數邏輯
}, function(err){
    // 若是promise對象調用了reject方法,則進入該函數邏輯
})

鏈式調用

由於promise對象中的then方法的返回值是一個新的promise對象,所以能夠實現鏈式調用。但後一個then方法的執行必須等待前一個then方法返回的promise對象狀態轉爲fulfilled或者rejected,若promise對象處於pending狀態下,則後一個then方法只能等待。函數

pro.then(function(res){
    // 第一個promise對象邏輯執行
    return newPro;// 返回一個新promise
}).then(function(res){
    // 對newPro這個對象進行處理
})
// ...能夠一直鏈式調用下去

異常捕捉

promise中的catch方法其實就是pro.then(null, rejection),用戶捕捉代碼運行中的錯誤異常。優化

pro.then(function(res){
    // 邏輯處理,但存在異常
}).catch(function(err){
    // 捕捉上一個then函數中所出現的異常錯誤
})

此外,catch方法的所捕捉的異常不只僅侷限於上一個then方法內,而是能夠把錯誤一直傳遞下來,直至遇到的第一個catch,而後被捕捉。如鏈式調用中:spa

pro.then(function(res){
    // 邏輯處理,但存在異常
}).then({
    // 邏輯處理
}).catch(function(err){
    // 捕捉上面第一個出現異常的then函數中所出現的錯誤
})

promise.all

promise.all方法能夠接受一個由promise組成的數組做爲參數,包裝成一個新的promise對象,而且按照數組中promise的順序進行異步執行。如:code

let pro1 = new Promise(function(resolve, reject){});
let pro2 = new Promise(function(resolve, reject){});
let pro3 = new Promise(function(resolve, reject){});

let proAll = promise.all([pro1, pro2, pro3]);

proAll的狀態由pro1,pro2,pro3三者共同決定:
①pending: 處理中,pro1,pro2,pro3中無rejected且存在pending狀態。
②rejected: pro1,pro2,pro3中存在一個rejected。
③fulfilled:pro1,pro2,pro3三者均爲fulfilled。對象

當proAll的狀態爲fulfilled時,會返回一個數組,該數組中的元素則是上面由promise組成的數組相對應執行後的結果。

promise.race

promise.race所接受的參數與promise.all一致,但promise.race的返回值則是由pro1,pro2,pro3三者中最早完成的promise對象決定,而且返回值爲該最先完成的promise對象的返回值。

let proAll = promise.race([pro1, pro2, pro3]);

promise.resolve

promise.resolve方法能將一個對象轉換成promise對象

let newPro = promise.resolve(obj);

①若obj不具備then方法,則newPro直接變爲fulfilled狀態

let newPro = promise.resolve('i am not a promise');

newPro.then(function(str){
    console.log(str) // 輸出 i am not a promise
})

②若是obj本就是一個Promise對象,則promise.resolve會將obj直接返回。

promise.reject

promise.reject方法與promise.resolve同樣,能將一個對象轉換成promise對象,但返回的promise對象的狀態爲rejected。

async/await

async是關鍵詞,在一個函數名以前加上該關鍵詞,代表該函數內部有異步操做,而這異步操做應該返回一個promise對象,而且在這異步操做以前添加await關鍵詞。當函數執行的時候,遇到await則會先進行Promise的邏輯處理,帶promise的狀態再也不爲pending時再執行該函數後面的語句。

let pro = new Promise(function(resolve, reject){
    // 異步處理邏輯
    resolve();
})

async function asyncFunc(){
    // 正常執行的語句
    await pro;
    // 等待promise處理完以後再執行的語句
}

asyncFunc();

總結

promise的出現,爲咱們編寫異步函數定下很多規則,在優化咱們代碼的同時也能減小代碼量,並加強可讀性,但也需嚴格遵照promise/A+的規範進行promise的開發。

相關文章
相關標籤/搜索