JS 中的 Promise

Promise 是異步編程的解決方案,它能夠很方便的處理異步事件。一個 Promise 實例包含一個異步操做,這項異步操做只有三種狀態,pending 初始狀態,既不是成功,也不是失敗狀態,Resolved 成功完成,Rejected 異步操做失敗。javascript

Promise 的狀態不受外界影響並且一旦狀態改變,就不會再改變。java

建立 Promise

要建立 Promise 實例要用到 Promise 類,它接受一個函數做爲參數,函數接受兩個參數,這兩個參數也是函數,一個是當異步成功執行時須要調用的函數,一個是失敗時調用的函數。編程

建立 Promise 實例的參數函數,將會當即執行。數組

function getData(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = () => resolve(xhr.responseText); 
        // 將狀態變爲 Resolved 並傳入獲取到的數據
        xhr.onerror = () => reject(xhr.statusText);
        // 將狀態變爲 Rejected 並傳入錯誤信息
        xhr.send();
    })
}

//調用 getData 將返回一個 Promise 實例
複製代碼

Promise 的原型方法

Promise 一共有三個原型方法,then, catchfinallypromise

then

then 方法接受兩個函數參數,一個是成功時候執行,一個是失敗時執行。異步

並且then方法將會返回一個新的 Promise 實例,這就表明能夠進行鏈式操做。異步編程

當即調用resolvePromise,它then方法的參數函數會放到本次事件循環末尾。函數

let p1 = getData('http://www.a.cn')

let onFulfilled = data => console.log(data)
let onRejected = err => console.log(err)

p1.then(onFulfilled, onRejected)

// 當成功時將會調用第一個回調函數,並把 resolve 傳入的參數再所有傳入 onFulfilled 中

// 當成功時將會調用第二個回調函數,並把 resolve 傳入的參數再所有傳入 onRejected 中

let p2 = getData('http://www.a.cn')

p2.then(url => getData(url))
  .then(data => console.log(data)) // 鏈式操做
  
// ------------------

let p = new Promise(resolve => {
    console.log(1)
    resolve(3)
})

console.log(2)

setTimeout(() => console.log(4))
p.then(num => console.log(num))
// 打印順序是 1 2 3 4

複製代碼

catch

catch 方法接受一個函數參數onRejectedcatch其實就是then的第二個參數。post

catch方法通常放在最後面,前面then方法,將會冒泡到它這裏。ui

catch 返回的仍是一個 Promise 對象。不過catch捕獲不了後面的then方法拋出的錯誤固然catch方法中也能夠拋出錯誤。

let p3 = getData('http://a.com')

p3.then(data => console.log(data))
  .then(() => throw new Error('error')) // 拋出錯誤
  .then(() => console.log(1))
  .catch(err => console.log(err))
 
// catch 將會捕獲上面的錯誤,並且第三個 then 方法會被跳過
複製代碼

Promise 中未捕獲的錯誤不會終止腳本執行而是打印一個未捕獲 promise 錯誤提示。

finally

finally 方法接受一個函數參數onFinally。它無論 Promise 對象最後狀態如何,都會執行的操做。finally方法的回調函數不接受任何參數。

它返回一個設置了 finally 回調函數的Promise對象。

Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};

// finally 至關於返回一個已經帶兩個參數的 then 方法
複製代碼

Promise 方法

Promise 一共有 4 個靜態方法。分別是all, race, resolvereject

resolve

resolve 接受一個參數,返回一個狀態由給定value決定的Promise對象。

若是參數是 Promise 對象則直接返回。

若是參數是thenable(即,帶有then方法的對象),then 方法會做爲Promise的參數,當即執行。

若是是其餘值返回一個新的 Promise 對象,狀態爲resolved,該value傳遞給對應的then方法。

Promise.resolve(1).then(num => {
    console.log(num)
});
複製代碼

reject

reject 方法接受一個參數,返回一個狀態爲失敗的Promise對象,並將給定的失敗信息傳遞給對應的處理方法。

Promise.reject('error');
// 等同於
new Promise((resolve, reject) => reject('error'))
複製代碼

all

all 方法接受具備 iterable 接口 參數。

這個方法返回一個新的promise對象,該promise對象在iterable參數對象裏全部的promise對象都成功的時候纔會觸發成功,一旦有任何一個iterable裏面的promise對象失敗則當即觸發該promise對象的失敗。

這個新的promise對象在觸發成功狀態之後,會把一個包含iterable裏全部promise返回值的數組做爲成功回調的返回值,順序跟iterable的順序保持一致

若是這個新的promise對象觸發了失敗狀態,它會把iterable裏第一個觸發失敗的promise對象的錯誤信息做爲它的失敗錯誤信息。

參數中的每一個項目都是一個 Promise 對象,若是不是則用 resolve 方法轉換成 Promise 對象。

race

race 方法和 all 方法同樣,可是當iterable參數裏的任意一個子 Promise 被成功或失敗後,返回的 Promise 對象的狀態就變成這個子 Promise 對象的狀態,它的值或錯誤信息也會傳遞給返回 Promise 對象的回調函數。

Promise 的屬性

Promise 一共有兩個屬性,lengthprototype

length屬性,其值老是爲 1 (構造器參數的數目)。

相關文章
相關標籤/搜索