1.含義
它由社區(qū)最早提出和實(shí)現(xiàn)贱案,ES6將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn)肛炮,統(tǒng)一了用法,原生提供了Promise對(duì)象侨糟。
所謂的Promise就是一容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束事件的結(jié)秕重。從語(yǔ)法上說(shuō),從它之中可以獲取異步操作的的消息菱魔。
特點(diǎn):
(1) 對(duì)象不受外界所干擾。
promise對(duì)象代表一個(gè)異步操作。它有三種狀態(tài)分別為Pending(進(jìn)行中)、Resolved(已完成雏节,又稱(chēng) Fulfilled)和Rejected(已失斒どぁ)。只有異步操作的結(jié)果钩乍,可以決定當(dāng)前是哪一種狀態(tài)变过,任何其他操作都無(wú)法改變這個(gè)狀態(tài)。這也是Promise這個(gè)名字的由來(lái)涝涤,它的英語(yǔ)意思就是“承諾”媚狰,表示其他手段無(wú)法改變。
(2) 狀態(tài)一旦確定就不會(huì)改變阔拳。
Promise對(duì)象的狀態(tài)改變崭孤,只有兩種可能:從Pending變?yōu)镽esolved和從Pending變?yōu)镽ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了裳瘪,不會(huì)再變了土浸,會(huì)一直保持這個(gè)結(jié)果。
缺點(diǎn):
首先彭羹,無(wú)法取消Promise黄伊,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消派殷。其次还最,如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤毡惜,不會(huì)反應(yīng)到外部拓轻。第三,當(dāng)處于Pending狀態(tài)時(shí)经伙,無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)扶叉。
- 用法
Promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來(lái)生成Promise實(shí)例帕膜。
var promise = new Promise(function (resolve, reject) {
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
Promise實(shí)例生成以后枣氧,可以用then方法分別指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)。
promise.then(() =>{
// success
}, () => {
// failure
})
then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)垮刹。第一個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)镽esolved時(shí)調(diào)用达吞,第二個(gè)回調(diào)函數(shù)是Promise對(duì)象的狀態(tài)變?yōu)镽eject時(shí)調(diào)用。其中荒典,第二個(gè)函數(shù)是可選的酪劫,不一定要提供。這兩個(gè)函數(shù)都接受Promise對(duì)象傳出的值作為參數(shù)寺董。
實(shí)例:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done')
})
}
timeout(100, then((value) => {
console.log(value)
}))
上面代碼中覆糟,timeout方法返回一個(gè)Promise實(shí)例,表示一段時(shí)間以后才會(huì)發(fā)生的結(jié)果螃征。過(guò)了指定的時(shí)間(ms參數(shù))以后搪桂,Promise實(shí)例的狀態(tài)變?yōu)镽esolved,就會(huì)觸發(fā)then方法綁定的回調(diào)函數(shù)盯滚。
注意:Promise新建后就會(huì)立即執(zhí)行踢械。
- Promise.prototype.then()
Promise實(shí)例具有then方法,也就是說(shuō)魄藕,then方法是定義在原型對(duì)象Promise.prototype上的内列。then方法返回的是一個(gè)新的Promise實(shí)例(注意,不是原來(lái)那個(gè)Promise實(shí)例)背率。因此可以采用鏈?zhǔn)綄?xiě)法话瞧,即then方法后面再調(diào)用另一個(gè)then方法嫩与。
4.promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)交排。
- promise.all()
Promise.all方法用于將多個(gè)Promise實(shí)例划滋,包裝成一個(gè)新的Promise實(shí)例.
var p = Promise.all([p1, p2, p3])
6.Promise.race()
Promise.race方法同樣是將多個(gè)Promise實(shí)例,包裝成一個(gè)新的Promise實(shí)例埃篓。
- promise.resolve()
有時(shí)需要將現(xiàn)有對(duì)象轉(zhuǎn)為Promise對(duì)象处坪,Promise.resolve方法就起到這個(gè)作用。
Promise.resolve('foo')
// 等價(jià)于
new Promise(resolve => resolve('foo'))
promise.reject()
Promise.reject(reason)方法也會(huì)返回一個(gè)新的 Promise 實(shí)例架专,該實(shí)例的狀態(tài)為rejected同窘。promise.try()
實(shí)際開(kāi)發(fā)中,經(jīng)常遇到一種情況:不知道或者不想?yún)^(qū)分部脚,函數(shù)f是同步函數(shù)還是異步操作想邦,但是想用 Promise 來(lái)處理它。因?yàn)檫@樣就可以不管f是否包含異步操作委刘,都用then方法指定下一步流程丧没,用catch方法處理f拋出的錯(cuò)誤。一般就會(huì)采用下面的寫(xiě)法钱雷。
promise.resolve().then(f)
promise原理實(shí)現(xiàn)
- 構(gòu)造一個(gè)Promise實(shí)例需要給Promise構(gòu)造函數(shù)傳入一個(gè)函數(shù)骂铁。傳入的函數(shù)需要有兩個(gè)形參,兩個(gè)形參都是function類(lèi)型的參數(shù)罩抗。分別是resolve和reject
- Promise上還有then方法,then 方法就是用來(lái)指定Promise 對(duì)象的狀態(tài)改變時(shí)確定執(zhí)行的操作灿椅,resolve 時(shí)執(zhí)行第一個(gè)函數(shù)(onFulfilled)套蒂,reject時(shí)執(zhí)行第二個(gè)函數(shù)(onRejected)
- 當(dāng)狀態(tài)變?yōu)閞esolve時(shí)便不能再變?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);
}
}