Promise 是異步編程的解決方案,它能夠很方便的處理異步事件。一個 Promise 實例包含一個異步操做,這項異步操做只有三種狀態,pending
初始狀態,既不是成功,也不是失敗狀態,Resolved
成功完成,Rejected
異步操做失敗。javascript
Promise 的狀態不受外界影響並且一旦狀態改變,就不會再改變。java
要建立 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 一共有三個原型方法,then
, catch
和 finally
。promise
then
方法接受兩個函數參數,一個是成功時候執行,一個是失敗時執行。異步
並且then
方法將會返回一個新的 Promise 實例,這就表明能夠進行鏈式操做。異步編程
當即調用resolve
的Promise
,它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
方法接受一個函數參數onRejected
,catch
其實就是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
方法接受一個函數參數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 一共有 4 個靜態方法。分別是all
, race
, resolve
和 reject
。
resolve
接受一個參數,返回一個狀態由給定value決定的Promise對象。
若是參數是 Promise 對象則直接返回。
若是參數是thenable(即,帶有then方法的對象),then 方法會做爲Promise
的參數,當即執行。
若是是其餘值返回一個新的 Promise 對象,狀態爲resolved,該value傳遞給對應的then方法。
Promise.resolve(1).then(num => {
console.log(num)
});
複製代碼
reject
方法接受一個參數,返回一個狀態爲失敗的Promise對象,並將給定的失敗信息傳遞給對應的處理方法。
Promise.reject('error');
// 等同於
new Promise((resolve, reject) => reject('error'))
複製代碼
all
方法接受具備 iterable 接口 參數。
這個方法返回一個新的promise對象,該promise對象在iterable參數對象裏全部的promise對象都成功的時候纔會觸發成功,一旦有任何一個iterable裏面的promise對象失敗則當即觸發該promise對象的失敗。
這個新的promise對象在觸發成功狀態之後,會把一個包含iterable裏全部promise返回值的數組做爲成功回調的返回值,順序跟iterable的順序保持一致
若是這個新的promise對象觸發了失敗狀態,它會把iterable裏第一個觸發失敗的promise對象的錯誤信息做爲它的失敗錯誤信息。
參數中的每一個項目都是一個 Promise 對象,若是不是則用 resolve
方法轉換成 Promise 對象。
race
方法和 all
方法同樣,可是當iterable
參數裏的任意一個子 Promise 被成功或失敗後,返回的 Promise 對象的狀態就變成這個子 Promise 對象的狀態,它的值或錯誤信息也會傳遞給返回 Promise 對象的回調函數。
Promise 一共有兩個屬性,length
和 prototype
。
length屬性,其值老是爲 1 (構造器參數的數目)。