[toc]
本文遵循的Promise/A+
規(guī)范實現(xiàn)一個簡略版本Promise, 用代碼理解規(guī)范中的每一句話.
Promise/A+
英文版規(guī)范, 中文版規(guī)范;- es6中Promise完整規(guī)范
- 瀏覽器中Promise實現(xiàn)
Promise 的狀態(tài)
規(guī)范描述
一個 Promise 的當前狀態(tài)必須為以下三種狀態(tài)中的一種:等待態(tài)(Pending)浊仆、完成態(tài)(Fulfilled)和拒絕態(tài)(Rejected)。
- 等待態(tài)(Pending)
處于等待態(tài)時,promise 需滿足以下條件:- 可以遷移至執(zhí)行態(tài)或拒絕態(tài)
- 完成態(tài)(Fulfilled)
處于執(zhí)行態(tài)時靖榕,promise 需滿足以下條件:- 不能遷移至其他任何狀態(tài)
- 必須擁有一個不可變的終值
- 拒絕態(tài)(Rejected)
處于拒絕態(tài)時蠢笋,promise 需滿足以下條件:- 不能遷移至其他任何狀態(tài)
- 必須擁有一個不可變的據(jù)因
代碼實現(xiàn)
采用類實現(xiàn):
class MyPromise {
}
實現(xiàn)構造函數(shù):
const _ = require('lodash');
const PENDING = 0;
const FULFILLED = 1;
const REJECTED = 2;
class MyPromise {
constructor(executor) {
if (!(this instanceof MyPromise)) {
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
}
if (!_.isFunction(executor)) {
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
}
this._status = PENDING;
this._value = undefined;
this._thenCallbacks = [];
this._reason = undefined;
try {
executor((...args) => this._resolve(...args), (...args) => this._reject(...args));
} catch(e) {
this._reject(e);
}
}
}
在構造函數(shù)中, 首先處理函數(shù)邊界, 然后初始化狀態(tài),終值(_value), 拒因(_reason)和then
的回調(diào)函數(shù)隊列; 最后調(diào)用傳入的executor
.executor
中用于控制Promise
狀態(tài)的變化.傳遞兩個回調(diào)函數(shù)作為參數(shù)媒殉,第一個參數(shù)叫做resove
起惕,第二個參數(shù)叫做 reject
, 在對象中的處理處理邏輯為:
_resolve(value) {
if (this._status !== PENDING) {
return;
}
this._status = FULFILLED;
this._value = value;
}
_reject(reason) {
if (this._status !== PENDING) {
return;
}
this._status = REJECTED;
this._reason = reason;
}
_resolve
, _reject
有狀態(tài)邊界判斷, 如果被調(diào)用多次, 采用首次調(diào)用并忽略剩下的調(diào)用._resolve
中只允許等待態(tài)轉為完成態(tài),然后接收終值._reject
中只允許等待態(tài)轉為拒絕態(tài), 然后接收拒因.
狀態(tài)的判斷保證
_resolve
,_reject
中主要邏輯在當前promise
中最多被執(zhí)行一次: 狀態(tài)最多改變一次;then
的回調(diào)函數(shù)最多調(diào)用一次.
Then函數(shù)
規(guī)范描述
一個promise
必須提供一個then
方法以訪問其當前值盅粪、終值和據(jù)因柜与。
promise
的then
方法接受兩個參數(shù):
promise.then(onFulfilled, onRejected)
參數(shù)可選
onFulfilled
和onRejected
都是可選參數(shù)巧勤。
- 如果
onFulfilled
不是函數(shù),其必須被忽略 - 如果
onRejected
不是函數(shù)弄匕,其必須被忽略
onFulfilled
特性
如果onFulfilled
是函數(shù):
- 當
promise
執(zhí)行結束后其必須被調(diào)用颅悉,其第一個參數(shù)為promise
的終值 - 在
promise
執(zhí)行結束前其不可被調(diào)用 - 其調(diào)用次數(shù)不可超過一次
調(diào)用時機
onFulfilled
和onRejected
只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
調(diào)用要求
onFulfilled
和onRejected
必須被作為函數(shù)調(diào)用(即沒有 this 值)注2
多次調(diào)用
then
方法可以被同一個promise
調(diào)用多次
當promise
成功執(zhí)行時,所有onFulfilled
需按照其注冊順序依次回調(diào)
當promise
被拒絕執(zhí)行時迁匠,所有的onRejected
需按照其注冊順序依次回調(diào)
返回
then
方法必須返回一個promise
對象
promise2 = promise1.then(onFulfilled, onRejected);
- 如果
onFulfilled
或者onRejected
返回一個值 x 剩瓶,則運行下面的Promise
解決過程:[[Resolve]](promise2, x)
- 如果
onFulfilled
或者onRejected
拋出一個異常e
,則promise2
必須拒絕執(zhí)行城丧,并返回拒因e
- 如果
onFulfilled
不是函數(shù)且promise1
成功執(zhí)行延曙,promise2
必須成功執(zhí)行并返回相同的值 - 如果 onRejected 不是函數(shù)且
promise1
拒絕執(zhí)行,promise2
必須拒絕執(zhí)行并返回相同的據(jù)因
代碼實現(xiàn)
需要在構造函數(shù)添加回調(diào)函數(shù)隊列:
constructor(executor) {
// ...
this._value = undefined;
this._thenCallbacks = [];
this._reason = undefined;
// ...
}
首先, 實現(xiàn)一個then
函數(shù).由于本章節(jié)代碼牽扯到很多部分, 所以盡量用代碼注釋來說明實現(xiàn)的規(guī)范:
then(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函數(shù)亡哄,其必須被忽略
const _onFulfilled = _.isFunction(onFulfilled) ? onFulfilled : void 0;
// 如果 onRejected 不是函數(shù)枝缔,其必須被忽略
const _onRejected = _.isFunction(onRejected) ? onRejected : void 0;
// then 方法可以被同一個 promise 調(diào)用多次
this._thenCallbacks.push([_onFulfilled, _onRejected]);
return new MyPromise((resolve, reject) => {
// 等待實現(xiàn)
});
}
onFulfilled
和onRejected
, 需要在_resove
或者reject
時被調(diào)用, 將resolve
, reject
改造為:
_resolve(value) {
if (this._status !== PENDING) {
return;
}
this._status = FULFILLED;
this._value = value;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(this._callThenCallbacks);
}
_reject(reason) {
if (this._status !== PENDING) {
return;
}
this._status = REJECTED;
this._reason = reason;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(this._callThenCallbacks);
}
雖然規(guī)范中沒有說明onFulfilled
和onRejected
必需為微任務(micro-task)還是宏任務(macro-task),但是其他實現(xiàn)基本都是基于微任務.
這里由于本文只是在node環(huán)境實現(xiàn),所以采用process.nextTick
來啟用微任務, 為了跨平臺, 一般的Promise實現(xiàn)框架, 都會使用多種方式來實現(xiàn)在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用, 如MutationObserver
, MessageChannel
, vertx
等, 最后可能使用setTimeout
實現(xiàn).
按照Promise/A+
規(guī)范來說,onFulfilled
和onRejected
只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用, 但是在nodejs
或者es6環(huán)境中的Promise
對象, 需要像下面的實現(xiàn):
_resolve(value) {
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(() => {
if (this._status !== PENDING) {
return;
}
this._status = FULFILLED;
this._value = value;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
// process.nextTick(() => this._callThenCallbacks());
this._callThenCallbacks();
});
}
_reject(reason) {
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(() => {
if (this._status !== PENDING) {
return;
}
this._status = REJECTED;
this._reason = reason;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// process.nextTick(() => this._callThenCallbacks());
this._callThenCallbacks();
});
}
對于比較流行的prmise polyfill庫
es-promise
的實現(xiàn),采用的是上面一種啟用微任務的時機, 對于babel中的墊片core-js中實現(xiàn)的promise
, 采用的是下一種啟用時機.
Then函數(shù).返回規(guī)范有復雜的要求,為了實現(xiàn)這些要求, 需要改變上面的then
函數(shù)的實現(xiàn):
then(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函數(shù),其必須被忽略
const _onFulfilled = _.isFunction(onFulfilled) ? onFulfilled : void 0;
// 如果 onRejected 不是函數(shù)蚊惯,其必須被忽略
const _onRejected = _.isFunction(onRejected) ? onRejected : void 0;
let childResolve;
let childReject;
const childPromise = new MyPromise((resolve, reject) => {
childResolve = resolve;
childReject = reject;
});
// then 方法可以被同一個 promise 調(diào)用多次
this._thenCallbacks.push([_onFulfilled, _onRejected, childResolve, childReject]);
return childPromise;
}
_callThenCallbacks
用于處理在promise
狀態(tài)改變后處理then
回調(diào)函數(shù)隊列. 在處理每一個then
回調(diào)函數(shù)后, 還需要對于then
回調(diào)函數(shù)返回的結果, 結合當前的promise
狀態(tài),調(diào)整當前then
函數(shù)返回的promise2
的狀態(tài):
// 調(diào)用then回調(diào)函數(shù)隊列
_callThenCallbacks() {
if (_.isEmpty(this._thenCallbacks)) {
return;
}
this._thenCallbacks.forEach(([onFulfilled, onRejected, childResolve, childReject]) => {
try {
if (this._status === FULFILLED && !onFulfilled) {
// 如果 onFulfilled 不是函數(shù)且 promise1 成功執(zhí)行愿卸, promise2 必須成功執(zhí)行并返回相同的值
childResolve(this._value);
return;
}
if (this._status === REJECTED && !onRejected) {
// 如果 onRejected 不是函數(shù)且 promise1 拒絕執(zhí)行, promise2 必須拒絕執(zhí)行并返回相同的據(jù)因
childReject(this._reason);
}
let x;
if (this._status === REJECTED && onRejected) {
// 當 promise 被拒絕執(zhí)行時拐辽,所有的 onRejected 需按照其注冊順序依次回調(diào)
// 其第一個參數(shù)為 promise 的拒因
// 必須被作為函數(shù)調(diào)用(即沒有 this 值)
x = onRejected(this._reason);
} else if (this._status === FULFILLED && onFulfilled) {
// 當 promise 成功執(zhí)行時,所有 onFulfilled 需按照其注冊順序依次回調(diào)
// 其第一個參數(shù)為 promise 的終值
// 必須被作為函數(shù)調(diào)用(即沒有 this 值)
x = onFulfilled(this._value);
}
// 如果 onFulfilled 或者 onRejected 返回一個值 x 擦酌,則運行下面的 Promise 解決過程
this._resolvePromise(x, childResolve, childReject);
} catch (error) {
childReject(error);
}
});
}
其中_resolvePromise
代表Promise解決過程, 將在下文說明.
Promise解決過程
規(guī)范描述
Promise解決過程是一個抽象的操作俱诸,其需輸入一個promise
和一個值,我們表示為[[Resolve]](promise, x)
赊舶,如果x
有then
方法且看上去像一個Promise睁搭,解決程序即嘗試使promise
接受x
的狀態(tài);否則其用x
的值來執(zhí)行 promise 笼平。
這種thenable
的特性使得Promise
的實現(xiàn)更具有通用性:只要其暴露出一個遵循 Promise/A+ 協(xié)議的then
方法即可园骆;這同時也使遵循 Promise/A+ 規(guī)范的實現(xiàn)可以與那些不太規(guī)范但可用的實現(xiàn)能良好共存。
運行[[Resolve]](promise, x)
需遵循以下步驟:
-
x
與promise
相等
如果x
為Promise寓调,則使promise 接受
x`的狀態(tài):- 如果
x
處于等待態(tài)锌唾,promise
需保持為等待態(tài)直至x
被執(zhí)行或拒絕 - 如果
x
處于執(zhí)行態(tài),用相同的值執(zhí)行promise
- 如果
x
處于拒絕態(tài)夺英,用相同的據(jù)因拒絕promise
- 如果
-
x
為對象或函數(shù)
如果x
為對象或者函數(shù):- 把
x.then
賦值給then
- 如果取
x.then
的值時拋出錯誤e
晌涕,則以e
為據(jù)因拒絕promise
- 如果
then
是函數(shù),將x
作為函數(shù)的作用域this
調(diào)用之痛悯。傳遞兩個回調(diào)函數(shù)作為參數(shù)余黎,第一個參數(shù)叫做resolvePromise
,第二個參數(shù)叫做rejectPromise
:- 如果
resolvePromise
以值y
為參數(shù)被調(diào)用载萌,則運行[[Resolve]](promise, y)
- 如果
rejectPromise
以據(jù)因r
為參數(shù)被調(diào)用惧财,則以據(jù)因r
拒絕promise
- 如果
resolvePromise
和rejectPromise
均被調(diào)用,或者被同一參數(shù)調(diào)用了多次扭仁,則優(yōu)先采用首次調(diào)用并忽略剩下的調(diào)用 - 如果調(diào)用
then
方法拋出了異常e
:- 如果
resolvePromise
或rejectPromise
已經(jīng)被調(diào)用垮衷,則忽略之 - 否則以
e
為據(jù)因拒絕promise
- 如果
- 如果
then
不是函數(shù),以x
為參數(shù)執(zhí)行promise
- 如果
- 把
如果
x
不為對象或者函數(shù)乖坠,以x為參數(shù)執(zhí)行
promise`
如果一個promise
被一個循環(huán)的thenable
鏈中的對象解決搀突,而[[Resolve]](promise, thenable)
的遞歸性質(zhì)又使得其被再次調(diào)用,根據(jù)上述的算法將會陷入無限遞歸之中瓤帚。算法雖不強制要求描姚,但也鼓勵施者檢測這樣的遞歸是否存在,若檢測到存在則以一個可識別的TypeError
為據(jù)因來拒絕promise
.
代碼實現(xiàn)
函數(shù)_resolvePromise
實現(xiàn), 采用代碼注釋說明:
// Promise 解決過程
_resolvePromise(x, childResolve, childReject) {
// x 與 promise 相等
if (x === this) {
// 如果 promise 和 x 指向同一對象戈次,以 TypeError 為據(jù)因拒絕執(zhí)行 promise
throw new TypeError("You cannot resolve a promise with itself");
}
// 如果 x 為 Promise 轩勘,則使 promise 接受 x 的狀態(tài)
if (x instanceof MyPromise) {
// 如果 x 處于等待態(tài)
console.log('======PENDING===', x._status);
if (x._status === PENDING) {
// promise 需保持為等待態(tài)直至 x 被執(zhí)行或拒絕
x.then(childResolve, childReject);
return;
}
// 如果 x 處于執(zhí)行態(tài)
if (x._status === FULFILLED) {
// 用相同的值執(zhí)行 promise
childResolve(x._value);
return;
}
// 如果 x 處于執(zhí)行態(tài)
if (x._status === REJECTED) {
// 用相同的值執(zhí)行 promise
childReject(x._reason);
return;
}
}
// x 為對象或函數(shù)
if (_.isObject(x) || _.isFunction(x)) {
// 把 x.then 賦值給 then
let then;
try {
then = x.then;
} catch (error) {
// 如果取 x.then 的值時拋出錯誤 e ,則以 e 為據(jù)因拒絕 promise
// 其實這里不需要捕獲, 因為最外層有捕獲, 這里為了保持跟規(guī)范一致
childReject(error);
return;
}
// 如果 then 是函數(shù)
if (_.isFunction(then)) {
// 將 x 作為函數(shù)的作用域 this 調(diào)用之
let called = false;
try {
then.call(x, (y) => {
// 如果 resolvePromise 和 rejectPromise 均被調(diào)用怯邪,或者被同一參數(shù)調(diào)用了多次,
// 則優(yōu)先采用首次調(diào)用并忽略剩下的調(diào)用
if (called) {
return;
}
called = true;
// 如果 resolvePromise 以值 y 為參數(shù)被調(diào)用
this._resolvePromise(y, childResolve, childReject);
}, (r) => {
// 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用绊寻,則忽略之
if (called) {
return;
}
called = true;
// 如果 rejectPromise 以據(jù)因 r 為參數(shù)被調(diào)用,則以據(jù)因 r 拒絕 promise
childReject(r);
});
} catch (error) {
// 如果調(diào)用 then 方法拋出了異常 e
// 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用,則忽略之
if (called) {
return;
}
// 否則以 e 為據(jù)因拒絕 promise
childReject(error);
}
return;
}
// 如果 then 不是函數(shù), 以 x 為參數(shù)執(zhí)行 promise
childResolve(x);
return;
}
// 如果 x 不為對象或者函數(shù), 以 x 為參數(shù)執(zhí)行 promise
childResolve(x);
}
全部代碼
const _ = require('lodash');
const PENDING = 0;
const FULFILLED = 1;
const REJECTED = 2;
class MyPromise {
constructor(executor) {
if (!(this instanceof MyPromise)) {
throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
}
if (!_.isFunction(executor)) {
throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
}
this._status = PENDING;
this._value = undefined;
this._thenCallbacks = [];
this._reason = undefined;
try {
executor((...args) => this._resolve(...args), (...args) => this._reject(...args));
} catch(e) {
this._reject(e);
}
}
_resolve(value) {
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(() => {
if (this._status !== PENDING) {
return;
}
this._status = FULFILLED;
this._value = value;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
// process.nextTick(() => this._callThenCallbacks());
this._callThenCallbacks();
});
}
_reject(reason) {
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
process.nextTick(() => {
if (this._status !== PENDING) {
return;
}
this._status = REJECTED;
this._reason = reason;
// 如果then的回調(diào)函數(shù)onFulfilled, onRejected為函數(shù)的話, 需要
// 在 promise 執(zhí)行結束前其不可被調(diào)用,當 promise 執(zhí)行結束后其必須被調(diào)用
// 其調(diào)用次數(shù)不可超過一次
// 只有在執(zhí)行環(huán)境堆棧僅包含平臺代碼時才可被調(diào)用
// process.nextTick(() => this._callThenCallbacks());
this._callThenCallbacks();
});
}
// 調(diào)用then回調(diào)函數(shù)隊列
_callThenCallbacks() {
if (_.isEmpty(this._thenCallbacks)) {
return;
}
this._thenCallbacks.forEach(([onFulfilled, onRejected, childResolve, childReject]) => {
try {
if (this._status === FULFILLED && !onFulfilled) {
// 如果 onFulfilled 不是函數(shù)且 promise1 成功執(zhí)行澄步, promise2 必須成功執(zhí)行并返回相同的值
childResolve(this._value);
return;
}
if (this._status === REJECTED && !onRejected) {
// 如果 onRejected 不是函數(shù)且 promise1 拒絕執(zhí)行, promise2 必須拒絕執(zhí)行并返回相同的據(jù)因
childReject(this._reason);
}
let x;
if (this._status === REJECTED && onRejected) {
// 當 promise 被拒絕執(zhí)行時冰蘑,所有的 onRejected 需按照其注冊順序依次回調(diào)
// 其第一個參數(shù)為 promise 的拒因
// 必須被作為函數(shù)調(diào)用(即沒有 this 值)
x = onRejected(this._reason);
} else if (this._status === FULFILLED && onFulfilled) {
// 當 promise 成功執(zhí)行時,所有 onFulfilled 需按照其注冊順序依次回調(diào)
// 其第一個參數(shù)為 promise 的終值
// 必須被作為函數(shù)調(diào)用(即沒有 this 值)
x = onFulfilled(this._value);
}
// 如果 onFulfilled 或者 onRejected 返回一個值 x 村缸,則運行下面的 Promise 解決過程
this._resolvePromise(x, childResolve, childReject);
} catch (error) {
childReject(error);
}
});
}
// Promise 解決過程
_resolvePromise(x, childResolve, childReject) {
// x 與 promise 相等
if (x === this) {
// 如果 promise 和 x 指向同一對象祠肥,以 TypeError 為據(jù)因拒絕執(zhí)行 promise
throw new TypeError("You cannot resolve a promise with itself");
}
// 如果 x 為 Promise ,則使 promise 接受 x 的狀態(tài)
if (x instanceof MyPromise) {
// 如果 x 處于等待態(tài)
console.log('======PENDING===', x._status);
if (x._status === PENDING) {
// promise 需保持為等待態(tài)直至 x 被執(zhí)行或拒絕
x.then(childResolve, childReject);
return;
}
// 如果 x 處于執(zhí)行態(tài)
if (x._status === FULFILLED) {
// 用相同的值執(zhí)行 promise
childResolve(x._value);
return;
}
// 如果 x 處于執(zhí)行態(tài)
if (x._status === REJECTED) {
// 用相同的值執(zhí)行 promise
childReject(x._reason);
return;
}
}
// x 為對象或函數(shù)
if (_.isObject(x) || _.isFunction(x)) {
// 把 x.then 賦值給 then
let then;
try {
then = x.then;
} catch (error) {
// 如果取 x.then 的值時拋出錯誤 e 梯皿,則以 e 為據(jù)因拒絕 promise
// 其實這里不需要捕獲, 因為最外層有捕獲, 這里為了保持跟規(guī)范一致
childReject(error);
return;
}
// 如果 then 是函數(shù)
if (_.isFunction(then)) {
// 將 x 作為函數(shù)的作用域 this 調(diào)用之
let called = false;
try {
then.call(x, (y) => {
// 如果 resolvePromise 和 rejectPromise 均被調(diào)用仇箱,或者被同一參數(shù)調(diào)用了多次,
// 則優(yōu)先采用首次調(diào)用并忽略剩下的調(diào)用
if (called) {
return;
}
called = true;
// 如果 resolvePromise 以值 y 為參數(shù)被調(diào)用
this._resolvePromise(y, childResolve, childReject);
}, (r) => {
// 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用,則忽略之
if (called) {
return;
}
called = true;
// 如果 rejectPromise 以據(jù)因 r 為參數(shù)被調(diào)用东羹,則以據(jù)因 r 拒絕 promise
childReject(r);
});
} catch (error) {
// 如果調(diào)用 then 方法拋出了異常 e
// 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用剂桥,則忽略之
if (called) {
return;
}
// 否則以 e 為據(jù)因拒絕 promise
childReject(error);
}
return;
}
// 如果 then 不是函數(shù), 以 x 為參數(shù)執(zhí)行 promise
childResolve(x);
return;
}
// 如果 x 不為對象或者函數(shù), 以 x 為參數(shù)執(zhí)行 promise
childResolve(x);
}
then(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函數(shù),其必須被忽略
const _onFulfilled = _.isFunction(onFulfilled) ? onFulfilled : void 0;
// 如果 onRejected 不是函數(shù)属提,其必須被忽略
const _onRejected = _.isFunction(onRejected) ? onRejected : void 0;
let childResolve;
let childReject;
const childPromise = new MyPromise((resolve, reject) => {
childResolve = resolve;
childReject = reject;
});
// then 方法可以被同一個 promise 調(diào)用多次
this._thenCallbacks.push([_onFulfilled, _onRejected, childResolve, childReject]);
return childPromise;
}
}
module.exports = MyPromise;