淺談Promise實(shí)現(xiàn)

Promise主要用于異步處理,用來解決傳統(tǒng)的回調(diào)地獄問題。

它是把異步處理規(guī)范起來,采用統(tǒng)一的接口來編寫,使得更規(guī)范化。

在實(shí)際項(xiàng)目中可以用來處理異步函數(shù),以及多個(gè)異步操作的處理,在

異步處理中定義異步方法(如ajax),在.then方法中處理結(jié)果,使得

邏輯更清晰,更易于維護(hù),而不是使用函數(shù)嵌套函數(shù)的方式。

Promise提供了all方法來處理多個(gè)異步程序全部調(diào)用完成后返回結(jié)果,

還提供了與之相對(duì)的race方法.

promise鏈?zhǔn)秸{(diào)用:會(huì)將前一個(gè)then的返回值(return)作為下一次

成功的回調(diào)函數(shù)的參數(shù)。

/**

* 實(shí)現(xiàn)一個(gè)Promise

*/

function Promise(task) {

? ? //接收一個(gè)處理函數(shù)

? ? let that = this;//緩存this

? ? //promise有三種狀態(tài)? 默認(rèn)為pending

? ? that.status = 'pending';

? ? that.onFulfilledFns = [];//所有成功的回調(diào)

? ? that.onRejectedFns = [];//所有失敗的回調(diào)

? ? that.value = undefined;

? ? function resolve(value) {

? ? ? ? //成功函數(shù)

? ? ? ? if(that.status == 'pending'){

? ? ? ? ? ? that.status = 'fulfilled';

? ? ? ? ? ? that.value = value;

? ? ? ? ? ? //執(zhí)行所有成功的回調(diào)

? ? ? ? ? ? that.onFulfilledFns.forEach(item=>item(value));

}

};

? ? function reject(reason) {

? ? ? ? //失敗函數(shù)

? ? ? ? if(that.status == 'pending'){

? ? ? ? ? ? that.status = 'rejected';

? ? ? ? ? ? that.value = reason;

? ? ? ? ? ? //執(zhí)行所有失敗的回到

? ? ? ? ? ? that.onRejectedFns.forEach(item=>item(reason));

}

};

? ? //立即執(zhí)行傳入的處理函數(shù)

? ? try{

? ? ? ? task(resolve,reject);

? ? }catch (err){

? ? ? ? reject(err)

}

};

function resolvePromise(promise2,x,resolve,reject) {

? ? let then;

? ? if(promise2 === x){

? ? ? ? return reject(new Error('循環(huán)引用'));

}

? ? if(x instanceof Promise){

? ? ? ? //判斷x的prototype所指向的對(duì)象是否存在Promise的原型鏈上

? ? ? ? if(x.status= 'pending'){

? ? ? ? ? ? x.then(function (y) {

? ? ? ? ? ? ? ? //遞歸 調(diào)用

? ? ? ? ? ? ? ? resolvePromise(promise2,y,resolve,reject);

? ? ? ? ? ? },reject)

? ? ? ? }else if(x.status == 'fulfilled'){

? ? ? ? ? ? resolve(x.value);

? ? ? ? }else if(x.status == 'rejected'){

? ? ? ? ? ? reject(x.value);

}

? ? }else if(x != null && typeof x == 'object' || typeof x == 'function'){

? ? ? ? try{

? ? ? ? ? ? then = x.then;

? ? ? ? ? ? if(typeof then == 'function'){

? ? ? ? ? ? ? ? then.call(x,function (y) {

? ? ? ? ? ? ? ? ? resolvePromise(promise2,y,resolve,reject);

? ? ? ? ? ? ? ? },function (y) {

? ? ? ? ? ? ? ? ? ? reject(y)

});

}

? ? ? ? }catch (e){

? ? ? ? ? ? reject(e);

}

? ? }else{

? ? ? ? resolve(x);

}

}

//then方法

Promise.prototype.then = function (onFulfilled, onRejected) {

? ? //假如沒有傳入異步處理程序則直接返回結(jié)果

? ? onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function (value) {

? ? ? ? return value;

};

? ? onRejected = typeof onRejected == 'function'?onRejected:function (reason) {

? ? ? ? return reason;

};

? ? var promise2;//用來實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用

? ? let that = this;

? ? if(that.status == 'fulfilled'){

? ? ? ? promise2 = new Promise(function (resolve,reject) {

? ? ? ? ? ? let x = onFulfilled(that.value);

? ? ? ? ? ? resolvePromise(promise2,x,resolve,reject);

});

? ? }else if(that.status == 'rejected'){

? ? ? ? promise2 = new Promise(function (resolve,reject) {

? ? ? ? ? ? let x = onRejected(that.value);

? ? ? ? ? ? reject(x);

});

? ? }else if(that.status == 'pending'){

? ? ? ? promise2 = new Promise(function (resolve,reject) {

? ? ? ? ? ? that.onFulfilledFns.push(function(){

? ? ? ? ? ? ? ? let x = onFulfilled(that.value);

? ? ? ? ? ? ? ? resolve(x);

});

? ? ? ? ? ? that.onRejectedFns.push(function () {

? ? ? ? ? ? ? ? let x = onRejected(that.value);

? ? ? ? ? ? ? ? reject(x);

});

});

? ? }else{

? ? ? ? promise2 = new Promise(function (resolve,reject) {

? ? ? ? ? ? reject('Promise內(nèi)部狀態(tài)錯(cuò)誤');

});

}

? ? return promise2;

};

Promise.resolve = function (val) {

? ? return new Promise(function (resolve,reject) {

? ? ? ? resolve(val);

});

};

Promise.reject = function (val) {

? ? return new Promise(function (resolve,reject) {

? ? ? ? reject(val);

});

};

Promise.all = function (arrs) {

? ? //all方法接收一個(gè)promise數(shù)組,數(shù)組中所有異步操作結(jié)束后返回一個(gè)新的promise

? ? if(typeof arrs == 'object' && arrs.length > 0){

? ? ? ? return new Promise(function (resolve,reject) {

? ? ? ? ? ? let result = [];//新的promise返回結(jié)果

? ? ? ? ? ? let indexNum = 0;//當(dāng)前完成幾個(gè)

? ? ? ? ? ? let resolved = function (index) {

? ? ? ? ? ? ? ? return function (data) {

? ? ? ? ? ? ? ? ? ? result[index] = data;

? ? ? ? ? ? ? ? ? ? indexNum++;

? ? ? ? ? ? ? ? ? ? if(indexNum == arrs.length){

? ? ? ? ? ? ? ? ? ? ? ? resolve(result);

}

}

};

? ? ? ? ? ? for(let i=0;i

? ? ? ? ? ? ? ? arrs[i].then(resolved(i),function (reason) {

? ? ? ? ? ? ? ? ? ? reject(reason);

});

};

});

? ? }else{

? ? ? ? return new Promise(function (resolve,reject) {

? ? ? ? ? ? reject(new Error('all方法傳入?yún)?shù)錯(cuò)誤'));

});

}

};

Promise.race = function (arrs) {

? ? if(typeof arrs == 'object' && arrs.length > 0){

? ? ? ? return new Promise(function (resolve,reject) {

? ? ? ? ? ? for(let i=0;i

? ? ? ? ? ? ? ? arrs[i].then(function (data) {

? ? ? ? ? ? ? ? ? ? resolve(data);

? ? ? ? ? ? ? ? },function (err) {

? ? ? ? ? ? ? ? ? ? reject(err);

});

};

});

? ? }else{

? ? ? return new Promise(function (resolve,reject) {

? ? ? ? ? reject(new Error('race方法傳入?yún)?shù)錯(cuò)誤'));

})

};

};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容