1.含義
它由社區(qū)最早提出和實現(xiàn),ES6將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象。
所謂的Promise就是一容器,里面保存著某個未來才會結(jié)束事件的結(jié)。從語法上說,從它之中可以獲取異步操作的的消息。
特點:
(1) 對象不受外界所干擾。
promise對象代表一個異步操作。它有三種狀態(tài)分別為Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失?。?。只有異步操作的結(jié)果,可以決定當前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變。
(2) 狀態(tài)一旦確定就不會改變。
Promise對象的狀態(tài)改變,只有兩種可能:從Pending變?yōu)镽esolved和從Pending變?yōu)镽ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結(jié)果。
缺點:
首先,無法取消Promise,一旦新建它就會立即執(zhí)行,無法中途取消。其次,如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯誤,不會反應(yīng)到外部。第三,當處于Pending狀態(tài)時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
- 用法
Promise對象是一個構(gòu)造函數(shù),用來生成Promise實例。
var promise = new Promise(function (resolve, reject) {
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise實例生成以后,可以用then方法分別指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)。
promise.then(() =>{
// success
}, () => {
// failure
})
then方法可以接受兩個回調(diào)函數(shù)作為參數(shù)。第一個回調(diào)函數(shù)是Promise對象的狀態(tài)變?yōu)镽esolved時調(diào)用,第二個回調(diào)函數(shù)是Promise對象的狀態(tài)變?yōu)镽eject時調(diào)用。其中,第二個函數(shù)是可選的,不一定要提供。這兩個函數(shù)都接受Promise對象傳出的值作為參數(shù)。
實例:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done')
})
}
timeout(100, then((value) => {
console.log(value)
}))
上面代碼中,timeout方法返回一個Promise實例,表示一段時間以后才會發(fā)生的結(jié)果。過了指定的時間(ms參數(shù))以后,Promise實例的狀態(tài)變?yōu)镽esolved,就會觸發(fā)then方法綁定的回調(diào)函數(shù)。
注意:Promise新建后就會立即執(zhí)行。
- Promise.prototype.then()
Promise實例具有then方法,也就是說,then方法是定義在原型對象Promise.prototype上的。then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以采用鏈式寫法,即then方法后面再調(diào)用另一個then方法。
4.promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯誤時的回調(diào)函數(shù)。
- promise.all()
Promise.all方法用于將多個Promise實例,包裝成一個新的Promise實例.
var p = Promise.all([p1, p2, p3])
6.Promise.race()
Promise.race方法同樣是將多個Promise實例,包裝成一個新的Promise實例。
- promise.resolve()
有時需要將現(xiàn)有對象轉(zhuǎn)為Promise對象,Promise.resolve方法就起到這個作用。
Promise.resolve('foo')
// 等價于
new Promise(resolve => resolve('foo'))
promise.reject()
Promise.reject(reason)方法也會返回一個新的 Promise 實例,該實例的狀態(tài)為rejected。promise.try()
實際開發(fā)中,經(jīng)常遇到一種情況:不知道或者不想?yún)^(qū)分,函數(shù)f是同步函數(shù)還是異步操作,但是想用 Promise 來處理它。因為這樣就可以不管f是否包含異步操作,都用then方法指定下一步流程,用catch方法處理f拋出的錯誤。一般就會采用下面的寫法。
promise.resolve().then(f)
promise原理實現(xiàn)
- 構(gòu)造一個Promise實例需要給Promise構(gòu)造函數(shù)傳入一個函數(shù)。傳入的函數(shù)需要有兩個形參,兩個形參都是function類型的參數(shù)。分別是resolve和reject
- Promise上還有then方法,then 方法就是用來指定Promise 對象的狀態(tài)改變時確定執(zhí)行的操作,resolve 時執(zhí)行第一個函數(shù)(onFulfilled),reject時執(zhí)行第二個函數(shù)(onRejected)
- 當狀態(tài)變?yōu)閞esolve時便不能再變?yōu)閞eject,反之同理。
function Promise(executor) {
const _this = this;
_this.status = 'pending';
_this.successValue = undefined;
_this.failValue = undefined;
function resolve(value) {
if (_this.status === 'pending') {
_this.status = 'resolved';
_this.successValue = value;
}
}
function reject(reason) {
if (_this.status === 'reject') {
_this.status = 'rejected';
_this.failValue = 'reject'
}
}
executor(resolve, reject);
}
Promise.prototype.then = function(onFailed, onRejected) {
const _this = this;
if (_this.status === 'resolved') {
onFailed(_this.successValue)
}
if (_this.status === 'rejected') {
onRejected(_this.failValue);
}
}