Promises/A+實現,一條規範對應一段代碼

NO IMAGE
目錄

1. Terminology

  1. “promise” is an object or function with a then method whose behavior conforms to this specification.
  2. “thenable” is an object or function that defines a then method.
  3. “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
  4. “exception” is a value that is thrown using the throw statement.
  5. “reason” is a value that indicates why a promise was rejected.

2. Requirements

2.1 Promise States

A promise must be in one of three states: pending, fulfilled, or rejected.

為了防止後續字符串寫錯,我們寫成三個常量來表示這三種狀態

const PENDING =  'pending';
const FULFILLED =  'fulfilled';
const REJECTED =  'rejected';

2.1.1 When pending, a promise:

  1. may transition to either the fulfilled or rejected state.

2.1.2 When fulfilled, a promise:

  1. must not transition to any other state.

  2. must have a value, which must not change.

2.1.3 When rejected, a promise:

  1. must not transition to any other state.

  2. must have a reason, which must not change.

Here, “must not change” means immutable identity (i.e. ===), but does not imply deep immutability.

class Promise {
constructor(executor) {
this.status = PENDING
let resolve = data => {
if (this.status === PENDING){
this.status = FULFILLED
this.value = data
}
}
let reject = reason => {
if (this.status === PENDING){
this.status = REJECTED
this.value = reason
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
}

2.2 The then Method

A promise must provide a then method to access its current or eventual value or reason.

A promise’s then method accepts two arguments:

promise.then(onFulfilled, onRejected)

所以 我們現在 寫

class Promise {
constructor(executor) {
// ...
}
then(onFulfilled, onRejected) {
}
}

2.2.1 Both onFulfilled and onRejected are optional arguments

  1. If onFulfilled is not a function, it must be ignored.

  2. If onRejected is not a function, it must be ignored.

class Promise {
constructor(executor) {
// ...
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected == 'function' ? onRejected : reason => { throw reason }
// 如果代碼執行到這,onFulfilled和onRejected必定為函數
}
}

如果不是函數,我們就忽略用戶的值,直接使用我們內部自定義的函數。

上面的函數實現緣由會在後面再次說明

2.2.2 If onFulfilled is a function

  1. it must be called after promise is fulfilled, with promise’s value as its first argument.

  2. it must not be called before promise is fulfilled.

  3. it must not be called more than once.

如果在給 Promise通過then綁定回調函數時,Promise的狀態已經是FULFILLED時,我們就直接執行傳進來的回調函數

then(onFulfilled,onRejected){
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
}

2.2.3 If onRejected is function

  1. it must be called after promise is rejected, with promise’s reason as its first argument.

  2. it must not be called before promise is rejected.

  3. it must not be called more than once.

then(onFulfilled,onRejected){
if (this.status === REJECTED) {
onRejected(this.value)
}
}

2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

3.1 Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures thatconFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

簡單來說,就是onFulfilledonRejected這些回調函數必須異步調用,這裡我們使用最簡單的方式,即setTimeout

只要把上面執行onFulfilledonRejected的代碼,放在setTimeout裡面,這樣就不會立即執行了。回調函數就可以異步執行了.

if (this.status === FULFILLED) {
let timer = setTimeout(() => {
clearTimeout(timer)
onFulfilled(this.value)
})
}
if (this.status === REJECTED) {
let timer = setTimeout(() => {
clearTimeout(timer)
onRejected(this.value)
})
}

2.2.5 onFulfilled and onRejected must be called as functions (i.e. with no this value). [3.2]

3.2 That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.

2.2.6 then may be called multiple times on the same promise.

上面我們處理的情況是,函數已經成功或者失敗時執行相應的回調函數

那在添加回調時,狀態還是pending,那我們就不應該執行回調函數了

另外我們對同一個Promise對象可以then多次,即在該對象上掛載多個成功或失敗回調函數

當promise成功或失敗時再依次執行。

那沒執行前,我們就需要緩存起來

因此我們設置兩個數組來存放回調函數

class Promise {
constructor(executor) {
// 定義存放 成功後 執行的回調數組
this.onResolvedCallbacks = []
// 定義存放 失敗後 執行的回調數組
this.onRejectedCallbacks = []
}
}

在執行then時,如果此時的Promise狀態還是pending,就把方法push到上述的數組裡。

Promise{
// ...
then(){
// ...
if (this.state === PENDING) {
preomise2 = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(onFulfilled)
this.onRejectedCallbacks.push(onRejected)
})
}
// ...
}
}
  1. If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.

  2. If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.

那當我們更改狀態時,即執行resolvereject時,就開始遍歷執行回調數組裡的函數

class Promise {
constructor(executor) {
// ...
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
let resolve = data => {
// ..
this.onResolvedCallbacks.forEach(cb => cb(this.value))
// ..
}
let reject = reason => {
// ..
this.onRejectedCallbacks.forEach(cb => cb(this.value))
// ..
}
// ...
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
}

但是我們再回顧

2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code.

我們的回調函數需要異步執行,而上面的代碼卻是會同步執行的,所以同理我們需要在這裡使用setTimeout來使代碼異步執行

上面代碼中遍歷取得的cb就是我們的onFulfilledonRejected

class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
let resolve = data => {
let timer = setTimeout(() => {
clearTimeout(timer)
if (this.status === PENDING) {
this.status = FULFILLED
this.value = data
// 遍歷執行成功回調
this.onResolvedCallbacks.forEach(cb => cb(this.value))
}
})
}
let reject = reason => {
let timer = setTimeout(() => {
clearTimeout(timer)
if (this.status === PENDING) {
this.status = REJECTED
this.value = reason
// 遍歷執行失敗回調
this.onRejectedCallbacks.forEach(cb => cb(this.value))
}
})
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
}

2.2.7 then must return a promise [3.3].

3.3 Implementations may allow promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can produce promise2 === promise1and under what conditions.

 promise2 = promise1.then(onFulfilled, onRejected);

那麼我們前面的操作應該都包裹在promise2 = new Promise(resolve, reject) =>{ }裡面,然後把promise2返回

那我們的回調函數返回的數據就可以通過Promise2.resolve(value)Promise2.reject(reason)的參數進行傳遞

我們就可以通過以下形式獲取到數據

let promise2 = new Promise((resolve, reject) => {
resolve('data')
reject('reason')
})
promise2.then(
data => console.log(data),
reason => console.log(reason)
)

所以現在我們把代碼都包裹在promise裡面

then(onFulfilled, onRejected) {
// ...
let promise2
if (this.status === FULFILLED) {
promise2 = new Promise((resolve, reject) => {
// ...
})
}
if (this.status === REJECTED) {
promise2 = new Promise((resolve, reject) => {
// ...
})
}
if (this.status === PENDING) {
promise2 = new Promise((resolve, reject) => {
// ...
})
}
return promise2
}

1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).

這裡我們需要再定義一個[[Resolve]](promise2, x)方法,我們就取名為resolvePromise,

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

用來解析promise,具體如何解析在後面會2.3說明

該方法是用來解析回調函數返回的值的,我們希望通過resolvereject傳遞過去的值是一個普通值,即非thenable的,具體細節在後面講.

2. If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.

如果是錯誤的話,一定是一個普通值,我們直接preject傳遞出去就可以了

if (this.status === FULFILLED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === REJECTED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === PENDING) {
promise2 = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(value => {
try {
let x = onFulfilled(value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(reason => {
try {
let x = onRejected(reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}

3. If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.

4. If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.

這就是前面講到的如果用戶傳遞進來的onFulFilledonRejected不是函數的話,我們就忽略掉,定義為內部的函數

onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected == 'function' ? onRejected : reason => { throw reason }

簡單來說就是把值往後拋,讓下個then可以獲取得到這個then的數據。

Promise
.resolve(4)
.then()
.then(val => console.log(val))

綜上,我們就把 then方法的全部代碼實現了

then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected == 'function' ? onRejected : reason => { throw reason };
let promise2
if (this.status === FULFILLED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === REJECTED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === PENDING) {
promise2 = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(value => {
try {
let x = onFulfilled(value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(reason => {
try {
let x = onRejected(reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
return promise2
};

接下來我們來看我們先前定義的resolvePromise

2.3 The Promise Resolution Procedure

現在來看解析promise過程了,就是我們剛剛寫的

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

我們再來明確下promise2和x是指向什麼

我們在執行then方法會返回一個新的Promise,即promise2

let p1 = new Promise((resolve, reject) => {resolve('數據')})
let promise2 = p1.then(data => {
x = data + '經過了p1處理'
return x
})
console.log(promise2); // Promise { <pending> }
promise2.then(data => console.log(data)) // 數據經過了p1處理
  • promise2指的是,p1.then方法返回的對象
  • x指的是p1.thenp1添加的回調函數執行後返回的值

如果x是普通值,就像上面一樣我們直接打印出來了

但是x可能是一個thenable對象

let p1 = new Promise((resolve, reject) => { resolve('數據') })
let promise2 = p1.then(() => {
let x = new Promise((resolve, reject) => { resolve('x是一個promise') })
return x
}
)
promise2.then(data => {
console.log(data); //x是一個promise
})

但是我們在執行代碼第8行輸出data時,輸出的卻是一個普通值,而不是輸出直接輸出new Promise((resolve, reject) => { resolve('x是一個promise') })

因為如果返回的值是一個thenable對象,我們就會解析成普通值後再返回

// ...
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject) //這裡就是對回調函數返回值進行解析
// ...

resolvePromise的目的就是如果x是普通值就直接執行promise2.resolve(x),如果不是普通值就進行解析後,直到把x轉換為普通值後再執行promise2.resolve(x),當然只要是錯誤了直接就執行promise2.reject(x)

那如何解析成普通值就是我們接下來要做的

2.3.1 If promise and x refer to the same object, reject promise with a TypeError as the reason.

function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循環引用'));
}
}

循環引用的情況

let p1 = new Promise((resolve, reject) => {
resolve()
})
let p2 = p1.then(() => p2)
p2.then(null, reason => {
console.log(reason); // TypeError: 循環引用
})

p1.then(() => p2)裡的() => p2就是我們的成功回調函數,返回p2,這裡返回的數據,即上述的x

2.3.2 If x is a promise, adopt its state [3.4]:

[3.3] Generally, it will only be known that x is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.

  1. If x is pending, promise must remain pending until x is fulfilled or rejected.

    如果x是一個Promise,我們必須等它完成(失敗或成功)後得到一個普通值時,才能繼續執行。

    那我們把要執行的任務放在x.then()的成功回調和失敗回調裡面即可,這就表示x完成後就會調用我們的代碼。

    • 如果成功時,執行promise2resolve(value)
  • 如果失敗時,執行promise2reject(reason)

但是對於成功的情況,我們還需要再考慮下,x.then成功回調函數的參數,我們稱為y,那y也可能是一個thenable對象

所以我們應該把上面的改成

  • 如果成功時,執行resolvePromise(promise2, y, resolve, reject)

這樣最終執行promise2.resolve(value)中的這個value就一定是一個非thenable對象

resolvePromise函數中,如果x不是 thenable對象就會執行resolve(x)從而結束遞歸.

這條屬於後面的規範,後面會講到

if (x instanceof Promise) {
if (x.status == PENDING) {
x.then(
y => resolvePromise(promise2, y, resolve, reject),
r => reject(r)
// reject //這麼寫也是可以的,只是為了和上面對稱,把reject用一個函數又包裝起來了
)
}
} 

在上面的代碼中yx(x為promise對象)成功返回的值,如果y是一個普通值

  1. If/when x is fulfilled, fulfill promise with the same value.

  2. If/when x is rejected, reject promise with the same reason.

if (x instanceof Promise) {
if (x.status == PENDING) {
x.then(
y => { resolvePromise(promise2, y, resolve, reject) },
r => reject(r)
)
} else x.then(resolve, reject);
}

如果x此時 已經是完成的,那我們直接把resolvereject傳遞進去, 就會立即執行了,因為是完成的,所以他的值一定是普通值

2.3.3 Otherwise, if x is an object or function,

以下的處理都是為了兼容性處理,當我們的promise和別的promise進行交互的時候,他們的promise可能是自己寫的也可能是引用第三方庫的,所以無法直接使用x instanceof Promise來判斷,我們就稱他們為thanable

thenable,表示一個對象或者函數擁有then方法,我們用段代碼表示

if (p !== null &&
(typeof p === 'object' ||typeof p === 'function') &&
typeof p.then === 'function') {
// p 為 thenable
} else {
// p 不為 thenable
}

當然,原生的promise一定是一個thenable

那說明,如果我們這裡實現了thenable的邏輯,上面的判斷x是一個promise的處理,完全可以刪除掉。

下面我們開始處理thenable

if (x instanceof Promise) {
// ...
} else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
// ...
}
  1. Let then be x.then. [3.5]

else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
let then = x.then;
}

3.5 This procedure of first storing a reference to x.then, then testing that reference, and then calling that reference, avoids multiple accesses to the x.then property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.

這裡的意思是,我們先不判斷then是不是方法,後面再判斷。

  1. If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.

    在獲取x.then是,可能報錯,所以我們需要try/catch起來,如果報錯了就執行reject

    當然,正常情況下是不會報錯的,下面代碼演示了報錯的情況

let obj = {}
Object.defineProperty(obj, 'then', {
get() {
throw Error('取then出異常了')
return function (onFulfilled, onReject) {
}
},
set() { }
})
console.log(obj.then());

所以上面獲取x.then的地方,應該用try/catch包住

else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
try{
let then = x.then;
}catch(e){
reject(e)
}
}
  1. If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where:

    1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).
    2. If/when rejectPromise is called with a reason r, reject promise with r.
    else 	if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
    try {
    let then = x.then;
    if (typeof then === 'function') {
    then.call(
    x,
    y => resolvePromise(promise2, y, resolve, reject),
    r => reject(r)
    )
    }
    } catch (e) {
    reject(e)
    }
    }
    

    x作為thenthis實際上就是執行以下代碼

    x.then(
    y => { resolvePromise(promise2, y, resolve, reject) },
    r => reject(r)
    )
    

    我們會發現代碼和上面xpromise時的處理一模一樣的

    1. If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.

    resolvePromiserejectPromise只能執行其中的一個,因為要符合狀態要麼是

    • pending → fulfilled

    • pending → rejected

    • pending只能改變一次

    如果resolvePromiserejectPromise同時執行了,pending就改變了兩次

    所以,我們使用一個變量called來限制

    if (x instanceof Promise) {
    // ...
    } else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
    //promise2是否已經resolve 或reject了
    let called = false;
    try {
    let then = x.then;
    if (typeof then == 'function') {
    then.call(
    x,
    y => {
    //防止promise會同時執行成功和失敗的回調
    //如果promise2已經成功或失敗了,則不會再處理了
    if (called) return;
    called = true;
    resolvePromise(promise2, y, resolve, reject);
    },
    r => {
    //防止promise會同時執行成功和失敗的回調
    //如果promise2已經成功或失敗了,則不會再處理了
    if (called) return;
    called = true;
    reject(r);
    });
    } catch (e) {
    // ...
    }
    }
    
    1. If calling then throws an exception e,
      1. If resolvePromise or rejectPromise have been called, ignore it.
      2. Otherwise, reject promise with e as the reason.

      同樣的道理,我們報錯這裡也需要進行限制

    if (x instanceof Promise) {
    // ...
    } else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
    //promise2是否已經resolve 或reject了
    let called = false;
    try {
    // ...
    } catch (e) {
    //防止promise會同時執行成功和失敗的回調
    //如果promise2已經成功或失敗了,則不會再處理了
    if (called) return;
    called = true;
    reject(e);
    }
    }
    
  2. If then is not a function, fulfill promise with x.

如果x是一個對象或者函數,但是x.then不是一個方法,那x也不符合thenable的定義,即x是一個普通值

那對於是普通值,我們當然是直接resolve就可以了

function resolvePromise(promise2, x, resolve, reject) {
// ...
if (x instanceof Promise) {
// ...
} else if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
try {
// ...
if (typeof then == 'function') {
// ...
} else {
// then 不是一個函數
resolve(x);
}
} catch (e) {
// ...
}
} else{
// ...
}
}

我們可以舉個例子

let p1 = Promise.resolve(1)
let p2 = p1.then(() => {
return {
name: 'wcdaren',
then: '不是方法'
}
})
p2.then(
data => console.log(`data:${data}`),
error => console.log(`error:${error}`)
)

上面返回的是一個對象,但是then屬性卻不是函數

2.3.4 If x is not an object or function, fulfill promise with x.

if (x instanceof Promise) {
// ...
} else if (x != null && ((typeof x == 'object') || (typeof x == 'function'))) {
// ...
} else {
// x 是一個普通值
resolve(x);
}

這裡的x就是最簡單,非promise非thenable,我們直接resovle處理就可以了。

他的情況就是

let p1 = Promise.resolve(1)
let p2 = p1.then(() => 1) // x 就是這裡的 1 走的是p2的resovle
p2.then(
data => console.log('p2.resvole', data), //執行p2的resolve
e => console.log('p2.reject', e)
)
// p2.resvole 1

測試

我們在後面的添加以下代碼

Promise.deferred = Promise.defer = function () {
var defer = {};
defer.promise = new Promise(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
})
return defer;
}
try {
module.exports = Promise
} catch (e) {
}

使用腳本測試

npm i -g promises-aplus-tests
promises-aplus-tests Promise.js

附帶全代碼

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循環引用'));
}
let then
let called = false
if (x instanceof Promise) {
if (x.status == PENDING) {
x.then(
y => resolvePromise(promise2, y, resolve, reject),
r => reject(r)
)
} else x.then(resolve, reject);
} else if (x != null && ((typeof x == 'object' || typeof x == 'function'))) {
try {
then = x.then;
if (typeof then == 'function') {
then.call(
x,
y => {
//防止promise會同時執行成功和失敗的回調
//如果promise2已經成功或失敗了,則不會再處理了
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
//防止promise會同時執行成功和失敗的回調
//如果promise2已經成功或失敗了,則不會再處理了
if (called) return;
called = true;
reject(r);
});
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
class Promise {
constructor(executor) {
// 設置狀態
this.status = PENDING
this.value = undefined
// 定義存放 成功後 執行的回調數組
this.onResolvedCallbacks = []
// 定義存放 失敗後 執行的回調數組
this.onRejectedCallbacks = []
let resolve = data => {
let timer = setTimeout(() => {
clearTimeout(timer)
if (this.status === PENDING) {
this.status = FULFILLED
this.value = data
this.onResolvedCallbacks.forEach(cb => cb(this.value))
}
})
}
let reject = reason => {
let timer = setTimeout(() => {
clearTimeout(timer)
if (this.status === PENDING) {
this.status = REJECTED
this.value = reason
this.onRejectedCallbacks.forEach(cb => cb(this.value))
}
})
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected == 'function' ? onRejected : reason => { throw reason };
let promise2
if (this.status === FULFILLED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === REJECTED) {
promise2 = new Promise((resolve, reject) => {
let timer = setTimeout(() => {
clearTimeout(timer)
try {
let x = onRejected(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
if (this.status === PENDING) {
promise2 = new Promise((resolve, reject) => {
this.onResolvedCallbacks.push(value => {
try {
let x = onFulfilled(value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
this.onRejectedCallbacks.push(reason => {
try {
let x = onRejected(reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
return promise2
}
}
// 測試
Promise.deferred = Promise.defer = function () {
var defer = {};
defer.promise = new Promise(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
})
return defer;
}
try {
module.exports = Promise
} catch (e) {
}

相關文章

Promise.all和Promise.race源碼實現

排序演化(三):快速

排序演化(二):歸併

排序演化(一):希爾