美團(tuán)實(shí)現(xiàn)的promise源碼分析
原文寫的有點(diǎn)繁瑣漠趁,下面是它的代碼加上直接看時(shí)候的理解分析 原文地址
promise有幾個(gè)要點(diǎn)要注意:
- 每個(gè)promise對象都有一個(gè)value值闯割,它就是 傳遞給.then注冊函數(shù)的的參數(shù)值
- then函數(shù)返回一個(gè)新的promise對象
- then的參數(shù)為兩個(gè)函數(shù) onFulfilled, onrejected 以onFulfilled舉例溜徙,如果onFulfilled這個(gè)函數(shù)返回的是一個(gè)普通的值時(shí)嘲更, 那么這個(gè)值就直接賦予.then本身返回的這個(gè)promise對象的value值蠢古,如果onFulfilled返回一個(gè)promise對象的時(shí)候, 這個(gè)是最麻煩的處理情況水由,(假設(shè)onFullfilled返回的promise為promiseB, 對應(yīng)的.then返回的promise為promiseC)叶组, 那么必須保證,promiseB的狀態(tài)確定后圆仔,才執(zhí)行promiseC的resolve(即確定promiseC的狀態(tài))垃瞧, 而且promiseB的value要設(shè)置為promiseC的value
- 回調(diào)是異步執(zhí)行的
- 注意是 每個(gè)then注冊的函數(shù),它的返回值都轉(zhuǎn)為 then生成的promise的resolve參數(shù)
理解好上面幾點(diǎn)坪郭,就可以看下面的分析了
function Promise(fn) {
var state = 'pending',
//這個(gè)value記錄的是promise本身值 即用于它.then(onFulfilled)的參數(shù)值
value = null,
//記錄它對應(yīng)的異步回調(diào)對象个从,當(dāng)resolve執(zhí)行的時(shí)候,會異步執(zhí)行這些函數(shù)
deferreds = [];
//then會將一下符合條件的回調(diào)加入 deferred
//須知
/* new Promise_A_(resolve => resolve()).then(onFulfilled_B_)_C_
最麻煩的是 onFulfilled 返回也返回一個(gè) promise對象 下面討論這種情況
* 假設(shè)第一個(gè) new Promise 為 Promise A
* onFulfilled 返回的promise 為 Promise B
* then 本身返回的Promise 為 Promise C
* 必須是 A 狀態(tài)確定即執(zhí)行resolve 然后在 B 狀態(tài)確定 然后再是 C狀態(tài)確定
* 那么如何才能確保上面的流程執(zhí)行歪沃?
* 由于執(zhí)行resolve狀態(tài)才能確定嗦锐, 那么上面執(zhí)行情況一定是
* A 中的 resolve 中 調(diào)用 B 的 resolve B的resolve中 調(diào)用C的resolve
* 參數(shù)如何傳遞? 利用好promise 里面的value就行
*/
this.then = function (onFulfilled, onRejected) {
//每個(gè)then自動返回一個(gè)promise,
return new Promise(function (resolve, reject) {
//這里可以獲取 這個(gè)then創(chuàng)建的promise的resolve函數(shù) 因?yàn)樗锩鏁{(diào)用fn(resolve)
//獲取這個(gè)resolve函數(shù)可以做流程控制 控制這個(gè)resolve什么時(shí)候執(zhí)行 也就是promise C
//什么時(shí)候狀態(tài)確定
//promiseC 什么時(shí)候狀態(tài)確定呢沪曙?它必須在 onFulfilled 返回的promiseB狀態(tài)確定后才能確定
//由于PromiseB 在PromiseA的 resolve函數(shù)里面執(zhí)行 所以我們暫時(shí)把 onFulfilled 和 這個(gè)resolve
//保存起來
//promise中的fn是 立即執(zhí)行的 不用擔(dān)心handle獲取不到數(shù)據(jù)
handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve: resolve,
reject: reject
});
});
};
//這個(gè)handler是非常重要的奕污,異步里面當(dāng)前promise狀態(tài)確定了以后也直接調(diào)用它
//之前說了 promsieA 狀態(tài)確定 才執(zhí)行promiseB的then C也同理
function handle(deferred) {
//當(dāng)當(dāng)前的promise對象為pendding時(shí)候 直接加入到異步回調(diào)中
if (state === 'pending') {
deferreds.push(deferred);
return;
}
//當(dāng)前promise狀態(tài)已經(jīng)確定了話 就直接執(zhí)行then參數(shù)函數(shù),當(dāng)然如果存在話
var cb = state === 'fulfilled' ? deferred.onFulfilled : deferred.onRejected,
ret;
//這里是非常巧妙的 如果then參數(shù)不處理的話液走,自動交給then返回的promise對象處理
//起到冒泡的作用
if (cb === null) {
cb = state === 'fulfilled' ? deferred.resolve : deferred.reject;
//如果then參數(shù)不出來 那么之前把promiseA的value復(fù)制給promiseC的resolve
cb(value);
return;
}
//如果then的參數(shù)處理了 比如onFulfilled
//那么把onFuillfilled的返回值 當(dāng)成value傳遞給promiseC
//這個(gè)返回值 分為兩種情況 一種為 promsie 一種為 普通值
//如果為promise的話 那么必須等待這個(gè)promiseB狀態(tài)確定后 promiseC才執(zhí)行它的resolve
ret = cb(value);
deferred.resolve(ret);
}
//執(zhí)行resolve即能確定自己的狀態(tài)
function resolve(newValue) {
//如果它的參數(shù)是promise的話
if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
var then = newValue.then;
if (typeof then === 'function') {
//如果resolve參數(shù)為promise對象的話碳默,那么先確定參數(shù)的promise狀態(tài)贾陷,然
//后在確定自己本身的promise狀態(tài),
// 這里就做到了流程控制嘱根,而且把自己本身的resolve髓废,reject傳遞在
//newValue的 then函數(shù),恰好還能接受newValue這個(gè)promse的內(nèi)置value该抒,
//這樣就既做到了流程控制慌洪,又十分巧妙的獲取了promsie的value
then.call(newValue, resolve, reject);
return;
}
}
//如果不是promise對象的話, 直接調(diào)用異步回調(diào) 而且設(shè)置promise對象的value
state = 'fulfilled';
value = newValue;
finale();
}
function reject(reason) {
state = 'rejected';
value = reason;
finale();
}
function finale() {
// resolve后執(zhí)行的回調(diào) 必須異步的
setTimeout(function () {
deferreds.forEach(function (deferred) {
handle(deferred);
});
}, 0);
}
fn(resolve, reject);
}