//申明常量 promise的3個(gè)基本狀態(tài)
const SUCCESS = 'fulfilled';
const FAIL = 'rejected';
const PENDING = 'pending';
//返回的那個(gè)新的promise x是then方法中的返回值
function resolvePromise(promise2,x,resolve,reject){
if(promise2 === x){
reject(new TypeError('TypeError: Chaining cycle detected for promise #<Promise>'));
}
let called;
//判斷x的類型
//promise 有n種實(shí)現(xiàn)方式 都符合這個(gè)規(guī)范 兼容別人的 promise
//怎么判斷 x是不是一個(gè) promise 看他有沒(méi)有then方法
if(typeof x === 'function' || (typeof x === 'object' && x != null)){
try{
let then = x.then; //取then可能會(huì)報(bào)錯(cuò)
if(typeof then === 'function'){
then.call(x,y=>{ //如果promise是成功的就把結(jié)果往下傳,如果失敗的就讓下一個(gè)人也失敗
if(called) return; //1)//為了辨別這個(gè)promise不能多次調(diào)用
called = true;
resolvePromise(promise2,y,resolve,reject)
},r=>{
if(called) return; //2)//為了辨別這個(gè)promise不能多次調(diào)用
called = true;
reject(r)
}) //避免取多次 不要使用x.then() 否則會(huì)再次取值
}else{
resolve(x)
}
}catch(e){
if(called) return; //3)//為了辨別這個(gè)promise不能多次調(diào)用
called = true;
reject(e)
}
}else{
resolve(x) // 只要是一個(gè)普通值就需要接著往下面拋
}
}
class Promise{
constructor(executor){ //executor 執(zhí)行器 只要new Promise()的時(shí)候就會(huì)執(zhí)行
this.status = PENDING; //默認(rèn)狀態(tài)為等待態(tài)
this.value = undefined; //then 回調(diào)成功的返回值
this.reason = undefined; //then 回調(diào)失敗的返回值
this.onResolveCallbacks = []; //成功所有的回調(diào) 只有pending的時(shí)候才存儲(chǔ)
this.onRejectedCallbacks = []; //失敗所有的回調(diào) 只有pending的時(shí)候才存儲(chǔ)
let resolve = (value)=>{ //成功回調(diào)函數(shù) 改變狀態(tài)并保存返回值
if(value instanceof Promise){ //如果resolve的結(jié)果是一個(gè)promise
return value.then(resolve,reject) //那么會(huì)讓這個(gè)promise執(zhí)行,將執(zhí)行后的結(jié)果再傳遞給 resolve或者reject中
}
if(this.status === PENDING){ //只有在等待態(tài)的時(shí)候才能改變狀態(tài)
this.value = value;
this.status = SUCCESS;
this.onResolveCallbacks.forEach(fn => fn())
}
}
let reject = (reason)=>{ //失敗回調(diào)函數(shù) 改變狀態(tài)并保存返回值
if(this.status === PENDING){ //只有在等待態(tài)的時(shí)候才能改變狀態(tài)
this.reason = reason;
this.status = FAIL;
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try{ //在new Promise的時(shí)候可能內(nèi)部會(huì)拋錯(cuò)誤啄骇,所以需要try catch
executor(resolve,reject); //只要new Promise()的時(shí)候就會(huì)執(zhí)行 并且可傳遞兩個(gè)回調(diào)函數(shù) 成功冠场、失敗
}catch(e){
reject(e);
}
}
then(onFulfilled,onRejected){ //根據(jù)狀態(tài)執(zhí)行不同的函數(shù)
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => {throw err};
let promise2;
//可以不停的調(diào)用then方法,返回了一個(gè)新的promise
promise2 = new Promise((resolve,reject)=>{
if(this.status === SUCCESS){
setTimeout(()=>{ //定時(shí)器解決調(diào)用resolvePromise的時(shí)候promise2為undefined
try{ //執(zhí)行的時(shí)候拋出錯(cuò)誤灾搏,需要try catch 捕獲
//調(diào)用當(dāng)前then方法的結(jié)果漂羊,來(lái)判斷當(dāng)前這個(gè)promise2是成功還是失敗
let x = onFulfilled(this.value)
//這里的x是普通值還是promise
//如果這個(gè)是promise呢稽寒?
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
}
if(this.status === FAIL){
setTimeout(()=>{
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
}
if(this.status === PENDING){ //多次調(diào)用并且pending的時(shí)候存儲(chǔ)函數(shù)
this.onResolveCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
})
this.onRejectedCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
})
}
})
return promise2;
}
catch(errCallback){ //用來(lái)捕獲錯(cuò)誤
return this.then(null,errCallback)
}
}
//希望測(cè)試一下這個(gè)庫(kù)是否符合promise A+規(guī)范
//promises-aplus-tests
Promise.defer = Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
promise的實(shí)現(xiàn)過(guò)程
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
- 文/潘曉璐 我一進(jìn)店門(mén)老虫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叶骨,“玉大人,你說(shuō)我怎么就攤上這事祈匙『龉簦” “怎么了天揖?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)跪帝。 經(jīng)常有香客問(wèn)我今膊,道長(zhǎng),這世上最難降的妖魔是什么伞剑? 我笑而不...
- 正文 為了忘掉前任斑唬,我火速辦了婚禮,結(jié)果婚禮上黎泣,老公的妹妹穿的比我還像新娘恕刘。我一直安慰自己,他們只是感情好抒倚,可當(dāng)我...
- 文/花漫 我一把揭開(kāi)白布雪营。 她就那樣靜靜地躺著,像睡著了一般衡便。 火紅的嫁衣襯著肌膚如雪献起。 梳的紋絲不亂的頭發(fā)上,一...
- 那天镣陕,我揣著相機(jī)與錄音谴餐,去河邊找鬼。 笑死呆抑,一個(gè)胖子當(dāng)著我的面吹牛岂嗓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鹊碍,決...
- 文/蒼蘭香墨 我猛地睜開(kāi)眼厌殉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了侈咕?” 一聲冷哼從身側(cè)響起公罕,我...
- 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耀销,沒(méi)想到半個(gè)月后楼眷,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
- 正文 獨(dú)居荒郊野嶺守林人離奇死亡熊尉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
- 正文 我和宋清朗相戀三年罐柳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狰住。...
- 正文 年R本政府宣布,位于F島的核電站蔗崎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏扰藕。R本人自食惡果不足惜缓苛,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望邓深。 院中可真熱鬧未桥,春花似錦、人聲如沸芥备。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萌壳。三九已至亦镶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間袱瓮,已是汗流浹背缤骨。 一陣腳步聲響...
- 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像燎斩,于是被迫代替她去往敵國(guó)和親虱歪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...