要 本身實現 Promise, 首先須要瞭解 原生 Promise 的一些 關鍵特性。javascript
原生 Promise的關鍵特性 整理以下:java
提供一個 構造函數 - Promise, 返回一個 promise 對象。數組
promise 對象 應包含 屬性: 狀態 - PromiseStatus(pending、resolved、rejected), 值 - PromiseValue。promise
promise 對象 的 初始狀態 爲 pending, 值 爲 undefined。緩存
使用 構造函數 時須要傳入一個 函數類型的參數 - fn, fn 須要在 promise 對象構建完成之後當即執行。bash
fn 有兩個 函數類型的參數 - resolve 和 reject。當 fn 內部的異步操做完成 之後,調用 resolve、reject 將 promise對象 的狀態變爲 終態(resolved / rejected)。異步
原生 Promise 中,resolve、reject 由 javascript引擎 提供,不須要咱們提供。當咱們本身實現 promise 時,須要提供 resolve、reject。函數
fn 在執行過程當中,若是 發生異常,promise 對象 的狀態會變爲 rejected。ui
resolve 用於將 promise實例對象的狀態 從 pending 置爲 resolved。this
使用的時候,須要傳入一個 參數,通常爲 fn 內部異步操做返回的結果,會做爲 promise 對象的值。
若是 沒有傳參數,promise 對象 的值爲 undefined。
若是傳入的參數是一個 promise 對象,那麼 傳入的 promise 對象的狀態會傳遞給當前 promise 對象, 具體狀況以下:
若是 傳入的 promise 對象的狀態爲 pending,那麼 當前 promise 對象的狀態爲 pending,等到 傳入的 promise 對象的狀態變爲終態 後, 當前 promise 對象的狀態纔會變爲相應的終態, 當前 promise 對象的值 會使用 傳入的 promise 對象的值 更新。
若是 傳入的 promise 對象的狀態爲 resolved, 那麼 當前 promise 對象的狀態會變爲 resolved,值爲傳入的promise對象的值。
若是 傳入的 promise 對象的狀態爲 rejected, 那麼 當前 promise 對象的狀態會變爲 rejected, 值爲傳入的promise對象的值。
reject 用於將 promise實例對象的狀態 從 pending 置爲 rejected。
使用的時候,須要傳入一個 參數,通常爲 fn 內部異步操做返回的異常,會做爲 promise 對象的值。參數也可爲 空。
和 resolve 不一樣,就算傳入的參數爲 promise 對象, 也 不會影響原 promise 對象的狀態。
promise對象的狀態 一旦發生變化成爲 終態, 就 不會再變化。
原型方法 - then,用於 註冊 當 promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback。
then 方法在使用的使用,須要傳入兩個 函數類型的參數- onFullfilled 和 onRejected。
當 promise對象 的狀態變爲 resolved 時,執行 onFullfilled。 執行 onFullfilled 時, 會傳入一個參數,該參數爲 promise 對象的值。
當 promise對象 的狀態變爲 rejected 時,執行 onRejected。 執行 onRejected 時, 也會傳入一個參數,該參數爲 promise 對象的值。
onFullfilled、onRejected 均可覺得 空。
then 方法會返回一個 新的 promise 對象, 初始狀態爲 pending。
新的 promise 對象的狀態 變爲 終態 時,可能遇到的狀況以下:
onFullfilled、onRejected 沒有 正確註冊。
沒有正確註冊,即 promise 對象 - p1 的狀態 變爲 resolved,發現沒有註冊onFullfilled, 或者 promise 對象的狀態 變爲 rejected,發現沒有註冊onRejected。
此時, p1.then() 返回的 promise對象-p2 的狀態爲 p1 的狀態,p2 的值也爲 p1 的值。
onFullfilled、onRejected 正確註冊,新的 promise 對象 會根據 onFullfilled / onRjected 的 返回值 修改狀態以及更新值, 具體狀況以下:
若是 返回值普通值(普通對象、數值、字符串等), 新的 promise 對象 的狀態爲 resolved,promise對象的 值 更新爲 返回值。
若是 沒有返回值,默認爲 return undefined,新的 promise 對象 的狀態爲 resolved,promise對象的 值 更新爲 undefined。
若是返回一個 promise對象 - p2,那麼 新的promise對象 - p1 的 狀態及值 會被影響。
p2 的狀態爲 pending,p1 的狀態爲 pending,當 p2 的狀態變爲 終態 時,p1 的狀態也變爲 對應的終態,值也更新。
p2 的狀態爲 resolved,p1 的狀態也爲 resolved,值爲 p2 的值。
p2 的狀態爲 rejected,p1 的狀態也爲 rejected,值爲 p2 的值。
原型方法 - catch,用於 註冊 當 promise 對象的狀態 變爲 rejected 時調用的 callback。
catch 方法在使用的時候,須要傳入一個 函數類型的參數- onRejected
當 promise對象 的狀態變爲 rejected 時,執行 onRejected。 執行 onRejected 時, 會傳入一個參數,該參數爲 promise 對象的值。
catch 方法會返回一個 新的 promise 對象, 初始狀態爲 pending,變爲 終態 的狀況和 then 方法一致。
原型方法 - finally,用於 註冊 當 promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback。
finally 方法在使用的使用,須要傳入一個 函數類型的參數- callback
當 promise 對象 的狀態變爲 終態(resolved/rejected) 時,執行 callback。callback 的參數爲 空, 即 callback 內部的操做不依賴 promise 對象 的值。
finally 方法會返回一個 promise對象, 初始狀態爲 pending,變爲 終態 的狀況參照 then。
在 then、catch 方法中,若是 onFullfilled / onRejected 的返回值 不是 promise 對象, 那麼 返回值 會做爲 新的 promise 對象的值。 finally 方法會有稍許不一樣,若是 callback的返回值 不是 promise 對象, 那麼 新的 promise 對象的值 爲 原 promise 對象的值。
靜態方法 - Promise.resolve, 用於 快速構建 一個 promise 對象。
使用 resolve 的時候,會傳入 一個參數。參數的不一樣, 會影響 返回的 promise 對象的狀態和值,以下:
參數爲一個 promise 對象,不作任何處理, 直接返回傳入的 promise 對象;
參數爲 thenable 對象,即具備 then 方法 的對象, 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 then方法的返回值;
參數爲 普通值, 即 非promise對象、非thenable對象, 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 傳入的參數;
參數爲 空, 返回一個 新的 promise 對象, 狀態爲 resolved, 值爲 undefined;
靜態方法 - Promise.reject,用於 快速構建 一個狀態爲 rejected 的 promise 對象。
和 Promise.resolve 方法不一樣, 無論傳入的參數是什麼值, 返回的的 promise 對象 的狀態爲 rejected, 值爲 傳入的參數。
靜態方法 - Promise.all,用於跟蹤多個 promise 對象的狀態變化。
all 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending。
當參數中 全部的 promise 對象的狀態 變爲 resolved 時, p1的狀態 纔會變爲 resolved,此時 p1的值 是一個 數組,數組元素 爲 參數數組中各個 promise 對象的值。
參數中 只要有一個 promise 對象的狀態變爲 rejected, p1的狀態 就會變爲 rejected, p1的值 爲 第一個狀態爲 rejected 的 promise 對象的值。
靜態方法 - Promise.race,用於跟蹤多個 promise 對象的狀態變化。
race 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending。
參數中 只要有一個 promise 對象的狀態變爲 終態, p1的狀態 就會變爲 相應的狀態, p1的值 爲 第一個狀態爲 終態 的 promise 對象的值。
靜態方法 - Promise.any,用於跟蹤多個 promise 對象的狀態變化。
any 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending。
當參數中 全部的 promise 對象的狀態 變爲 rejected 時, p1的狀態 纔會變爲 rejected,此時 p1的值 是一個 數組,數組元素 爲 參數數組中各個 promise 對象的值。
參數中 只要有一個 promise 對象的狀態變爲 resolved, p1的狀態 就會變爲 resolved, p1的值 爲 第一個狀態爲 resolved 的 promise 對象的值。
靜態方法 - Promise.allSetted,用於跟蹤多個 promise 對象的狀態變化。
allSettled 方法使用時需傳入 一個數組類型的參數, 數組中中包含若干個 promise 對象, 返回一個 promise 對象 - p1,狀態爲 pending。
當參數中 全部的 promise 對象的狀態變爲 終態, p1的狀態 就會變爲 resolved, 此時 p1的值 是一個 數組,數組元素 爲 參數數組中各個 promise 對象的值
微任務隊列。
在一個 事件循環 中,當 promise 對象的狀態 變爲 終態時, 會開啓一個 微任務隊列, 將 對應的callback 添加到 隊列 中。 當 事件循環 中的 同步代碼 執行完成之後,開始處理 微任務隊列 中的 任務。
微任務隊列 開始工做之後, 若是有 新的 promise 對象的狀態變爲終態, 會將 對應的callback 繼續添加到 微任務隊列 中等待處理。
微任務隊列 中的 全部任務處理完畢 之後就會被 清空,而後關閉微任務隊列,直到下一次事件循環中有 promise 對象的狀態變爲終態時從新開啓。
根據上述 原生promise 的 關鍵特性,咱們可本身動手逐步實現 Promise。實現過程以下:
模擬微任務隊列
在這裏, 咱們使用 setTimeout 和 一個數組 - queue 來模擬 微任務隊列,以下:
let queue = [] // 任務隊列
let flushing = false // 任務隊列未啓用
let index = 0
// 將任務添加到任務隊列中
// 若是是首次將任務添加到任務隊列中,啓動任務隊列,
// 並經過setTimeout實現同步代碼執行完成之後處理任務隊列中的任務
// 若是添加任務時, 任務隊列已啓動, 直接將任務添加到任務隊列中,等待處理
function queueTask(task) {
if (!queue.length) {
// 啓動任務隊列
flushing = true
// 等同步代碼執行完成之後, 處理任務隊列中的任務
setTimeout(flushQueue, 0)
}
// 將任務添加到任務列中
queue.push(task)
}
// 處理任務隊列中的任務
function flushQueue() {
// 遍歷任務隊列中的任務,處理每個任務
while(index < queue.length) {
queue[index].call()
index++
}
// 處理完成之後,清空並關閉任務隊列
queue = []
index = 0
flushing = false
}
複製代碼
構建 Promise 類
要實現 Promise,首先須要提供一個 Promise 類。一個 Promise 類 須要 構造函數,原型方法then、catch、finally, 靜態方法resolve、reject、all、race、any、allSetted。
其次,咱們還須要一些 輔助函數,exector、resolve、reject、handle。其中, resolve、reject 用於修改 promise 對象 的 狀態,exector 用於 執行構造 promise 對象時傳入的 fn,handle 用於處理 then、catch、finally 方法註冊的 callback。
class MyPromise {
// 構造函數
constructor(fn) {}
// 原型方法 - then
then(onFullfilled, onRejected) {}
// 原型方法 - catch
catch(onRejected) {}
// 原型方法 - finally
finally(callback) {}
// 靜態方法 - resolve
static resolve(value) {}
// 靜態方法 - reject
static reject(reason) {}
// 靜態方法 - all
static all(arr) {}
// 靜態方法 - race
static race(arr) {}
// 靜態方法 - any
static any(arr) {}
// 靜態方法 - allSetted
static allSetted(arr) {}
}
// 輔助函數,用於執行構建 promise 對象傳入的 fn
function exector(fn) {}
// 輔助函數,將 promise 對象的狀態變爲resolved
function resolve(promise, value) {}
// 輔助函數,將 promise 對象的狀態變爲rejectd
function reject(promise, value) {}
// 輔助函數,用於處理 promise 對象 的 callback
function handle(promise, handler)
複製代碼
實現構造函數
接下來,咱們首先來實現 構造函數 - constructor。
class MyPromise {
constructor(fn) {
// promise 對象的初始狀態爲 'pending'
this._status = 'pending'
// promise 對象的初始值爲 'undefined'
this._value = undefined
// 用於緩存註冊的callback,當狀態發生變動時,會遍歷並處理
this._handlers = []
this._effects = []
// then方法中會調用構造函數構建一個新的promise對象
// 使用構造函數的時候,不傳入fn,也就不會執行fn
if(!fn) return
// 執行 fn
exector(this, fn)
}
}
複製代碼
在構建 promise 對象 的時候,咱們會爲 promise 對象 添加以下屬性:_status、_value、_handlers、_effects。
_status 爲 promise 對象 的 狀態,初始值爲 'pending', 終態爲 'resolved' 和 'rejected'。
_value 爲 promise 對象 的值,初始值爲 undefined。
_handlers 用於緩存 promise 對象 經過 then、catch、finally 註冊的 callback。等 promise 對象 的 狀態 發生變化時,遍歷 _handlers 中的 callback 並處理。
_effects 中存儲的是 promise 對象。當咱們使用 resolve 方法修改 狀態 時,若是傳入的是一個 promise對象 - p1,那麼 p1 的狀態 會影響 原 promise 對象 - p2 的狀態。此時咱們會把 p2 添加到 p1 的 _effects 中, 等到 p1 的狀態 發生變動時, 通知 p2 更新。
輔助函數 exector、resolve、reject、handle
使用構造函數建立 promise 對象 時, 若是傳入了 fn, 須要經過輔助函數 exector 來執行 fn。exector 的過程以下:
function exector(promise, fn) {
try {
// 執行fn, 傳入 resolve 和 reject
fn(value => {resolve(promise, value)}, // resolve
reason => { reject(promise, reason)}) // reject
} catch(e) {
// 執行fn的過程當中,若是發生異常, 將promise對象的狀態置爲rejected
reject(promise, e)
}
}
複製代碼
執行fn的時候, 咱們傳入 通過包裝的函數 做爲 resolve 和 reject。當咱們拿到異步操做的結果後,將結果做爲參數傳入 resolve、reject,將 promise 對象 的狀態變爲 resolved、rejected。
經過輔助函數 resolve, 咱們能夠將 promise對象 的狀態置爲 resolved。
function resolve(promise, value) {
// 若是 promise對象的狀態已經爲終態, 直接返回
if (promise._status !== 'pending') return
if (value && typeof value === 'object') {
// 使用resolve時,若是傳入的是一個promise對象,promise對象的狀態會傳遞給當前promise對象
if (value instanceof MyPromise) {
// 傳遞狀態
promise._status = value._state
// 傳遞值
promise._value = value._value
if (value._status !== 'pending') {
// 若是傳入的promise對象的狀態是resolved, 那麼當前promise對象的狀態會變爲resolved
// 此時須要將當前promise對象註冊的callback所有添加到微任務隊列中
promise._handlers.forEach(handler => {
handle(promise, handler)
})
} else {
// 若是傳入的promise對象的狀態是 pending
// 須要將當前promise對象添加到傳入的promise對象的_effects列表中
// 等到傳入的promise對象的狀態發生變化時,通知當前promise對象進行狀態變化
value._effects.push(promise)
}
return
} else if (value.then && typeof value.then === 'function') {
// 若是傳入的是一個 thenable 對象
exector(promise, value.then.bind(value))
return
}
}
// 若是傳入的是普通值, 那麼將當前promise對象的狀態置爲resolved
promise._status = 'resolved'
// 傳入的值爲promise對象的值
promise._value = value
// 遍歷_handlers列表, then、catch、finally註冊的callback添加到微任務隊列中
promise._handlers.forEach(handler => {
handle(promise, handler)
})
// 通知_effects列表中的promise對象進行狀態變動
promise._effects.forEach(item => {
resolve(item, promise._value)
})
}
複製代碼
經過輔助函數 reject, 咱們能夠將 promise 對象 的狀態變爲 rejected。
function reject(promise, error) {
// 若是promise對象的狀態爲終態, 直接返回
if (promise._status !== 'pending') return
// promise 對象 的狀態變爲 rejected
promise._status = 'rejected'
// 傳入的值爲promise對象的值
promise._value = error
// 遍歷_handlers列表, then、catch、finally註冊的callback添加到微任務隊列中
promise._handlers.forEach(handler => {
handle(promise, handler)
})
// 通知_effects列表中的promise對象進行狀態變動
promise._effects.forEach(item => {
reject(item, promise._value)
})
}
複製代碼
經過輔助函數 handle, 咱們能夠將 promise對象 註冊的 callback 收集到 _handlers 列表 中。當 promise 對象 的狀態爲 終態 時, 將註冊的 callback 添加到 微任務隊列 中。
// handler是一個對象,裏面包含promise對象註冊的onFullfilled、onRejected 和 執行 'then'、'catch'、'finally'方法時返回的 promise對象
function handle(promise, handler) {
// 若是 promise 實例的狀態爲pending, 將註冊的callback先收集起來。
// 等promise對象的狀態變爲終態時,將callback添加到微任務隊列中
if (promise._status === 'pending') {
promise._handlers.push(handler)
return
}
// promise實例的狀態爲resolved或者rejected時, 將註冊的callback添加到微任務隊列中, 等待執行
queueTask(function() {
// 微任務隊列啓動後, 開始處理微任務隊列中的任務
// 若是promise 對象的狀態爲resolved, 獲取onFullfilled
// 若是promise 對象的狀態爲rejected, 獲取onRejected
let cb = promise._status === 'resolved' ? handler.onFullfilled : handler.onRejected;
if (!cb) {
// 若是callback沒有正確註冊
// 'p2 = p1.then(onFullfilled, onRejected)'
// 若是p1沒有正確註冊callback,即p1爲resolved,卻沒有註冊onFullfilled;
// 或者 p1爲rejected,卻沒有註冊onRejected
if (promise.status === 'resolved') {
// 若是p1的狀態爲resolved,將p2的狀態置爲resolved
// p2的值爲p1的值
resolve(handler.promise, promise._value)
} else {
// 若是p1的狀態爲rejected,將p2的狀態置爲rejected
// p2的值爲p1的值
reject(handler.promise, promise._value)
}
return
}
// 若是callback有正確註冊
try {
// 執行callback
let res = cb(promise._value)
// 'p2 = p1.then()'
// 將p2的狀態置爲resolved, 並使用callback的返回值做爲p2的值
resolve(handler.promise, res)
} catch (e) {
// callback執行異常,將p2的狀態置爲rejected,將異常做爲p2的返回值
reject(handler.promise, e)
}
})
}
複製代碼
then
promise對象 構建完成之後, 咱們須要經過 then 方法來註冊 onFullfilled 和 onRejected。等到 promise 對象 的狀態變爲終態時,執行對應的 callback。
class Promise {
then(onFullfilled, onRejected) {
let P = this.constructor
// promise.then 方法會返回一個 promise 實例
let res = new P()
// 若是當前promise對象的狀態爲pending,會將{onFullfilled, onRejected,..} 添加到_handlers中,等到狀態變爲終態, 再作處理
// 若是當前promise對象的狀態爲終態, 會將callback添加到微任務隊列中
handle(this, {
onFullfilled,
onRejected,
promise: res
})
// 返回一個新的promise對象
return res
}
}
複製代碼
catch
catch 方法用於註冊當 promise 對象的狀態 變爲 rejected 時調用的 callback。
catch(onRejected) {
this.then(null, onRejected)
}
複製代碼
finally
finally,用於 註冊 當 promise 對象的狀態 變爲 終態(resolved/rejected) 時調用的 callback。
// 只要promise實例的狀態發生變化, 都會執行,返回一個promise實例
// promise實例的值爲上一個promise實例的值
finally(callback) {
let P = this.constructor
let res = new P()
handle(this, {
onFullfilled: () => {
// 當原promise實例的狀態變爲resolved時,執行callback
callback()
// 返回原promise對象的值做爲新promise對象的值
return this._value
},
onRejected: () => {
// 當原promise實例的裝填變爲rejected, 執行callback
callback()
// 返回原promise對象的值做爲新promise對象的值
return this._value
},
promise: res
})
// 返回一個新的promise對象
return res
}
複製代碼
Promise.resolve
靜態方法 resolve, 用於快速構建一個 promise對象,promise 對象的狀態 有傳入的參數決定。
static resolve(value) {
// 傳入一個promise對象, 直接返回參數
if (value instanceof MyPromise) return value
// 傳入一個thenable對象,構建一個新的promise對象
// thenable對象的狀態和值決定新的promise對象的狀態和值
if (value && value.then && typeof value.then === 'function') {
return new MyPromise(value.then.bind(value))
}
// 其餘類型的參數,直接返回狀態爲resolved的promise對象
// promise對象的值爲傳入的參數
let promise = new MyPromise()
promise._status = 'resolved'
promise._value = value
return promise
}
複製代碼
Promise.reject
靜態方法 reject,用於快速構建一個狀態爲 rejected 的 promise對象,傳入的參數爲 promise 對象 的值。
static reject(value) {
let promise = new MyPromise()
promise._state = 'rejected'
promise._value = value
return promise
}
複製代碼
Promise.all
靜態方法 all 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態都爲 resolved, 返回的 新的 promise 對象 的狀態變爲 resolved, 不然爲 rejected。
static all(arr) {
var args = Array.prototype.slice.call(arr)
// all 方法會返回一個新的promise對象
return new MyPromise(function(resolve, reject) {
if (args.length === 0) return resolve([])
let remain = args.length
// 若是promise對象的狀態爲resolved, 把promise對象的值先緩存起來
// 若是promise對象的狀態爲pending,等promise的狀態變爲resolved,把promise對象的狀態緩存起來
// 當全部的promise對象的狀態爲resolved時,將新的promise對象的狀態置爲resolved, 使用緩存的數組做爲新的promise對象的值
// 若是promise對象的狀態爲rejected,直接將新的promise對象的狀態置爲rejected
function func(index, val) {
if (typeof val === 'object') {
if (val instanceof MyPromise) {
// promise對象的狀態爲resolved, 緩存promise對象的值
if (val._status === 'resolved') return func(index, val._value)
// promise對象的狀態爲rejected,新的promise對象的狀態爲rejected
if (val._status === 'rejected') {
// 新的promise對象的值爲第一個狀態爲rejected的promise對象的值
reject(val._value)
return false
}
// promise對象的狀態爲pending
val.then(value => {
func(index, value)
}, reject)
return true
} else if (val.then && typeof val.then === 'function') {
// 傳入的參數是thenable對象
let p = new MyPromise(val.then.bind(val))
p.then(value => {
func(index, value)
}, reject)
return true
}
}
// 若是promise對象的狀態爲resolved, 緩存promise對象的值
args[index] = val
// 傳入的promise對象的狀態都變爲resolved, 返回的promise對象的狀態變爲resolved
// 值爲一個數組,包含全部promise對象值
if (--remain === 0) {
resolve(args)
}
return true
}
// 遍歷傳入的promise對象
for(let i = 0; i < args.length; i++) {
if (!func(i, args[i])) return false
}
})
}
複製代碼
Promise.race
靜態方法 race 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態只要有一個是 終態 時, 返回的 新的 promise 對象 的狀態變爲 相應的狀態。
static race(arr) {
// 返回一個promise對象
return new MyPromise(function(resolve, reject) {
arr.forEach(function(value){
// arr 中只要有一個 promise 實例的狀態爲發生變化, 返回的 promise的狀態就會發生變化
// 返回的promise對象的值爲參數中第一個狀態變化的promise對象的值
MyPromise.resolve(value).then(resolve, reject);
});
})
}
複製代碼
Promise.allSettled
靜態方法 allSettled 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的狀態都變爲 終態 時, 返回的 新的 promise 對象 的狀態變爲 resolved。
static allSettled(arr) {
var args = Array.prototype.slice.call(arr)
// 返回一個新的promise對象
return new MyPromise(function(resolve, reject) {
if (args.length === 0) return resolve([])
let remain = args.length
function func(index, val) {
if (typeof val === 'object') {
// 參數爲promise對象
if (val instanceof MyPromise) {
// promise對象的狀態爲resolved, 緩存promise對象的值
if (val._status === 'resolved') return func(index, val._value)
// promise對象的狀態爲rejected, 緩存promise對象的值
if (val._status === 'rejected') return func(index, val._value)
// promise對象的狀態爲pending, 等promise對象的狀態變爲終態時,緩存promise對象的值
val.then((value) => {
func(index, value)
}, (error) => {
func(index, error)
})
} else if (val.then && typeof val.then === 'function') {
// 參數爲thenable對象
let p = new MyPromise(val.then.bind(val))
p.then((value) => {
func(index, value)
}, (error) => {
func(index, error)
})
}
}
// 參數爲普通值,直接緩存
args[index] = val
if (--remain === 0) {
// 全部的promise對象的狀態都爲終態,將返回的promise對象的狀態變爲resolved
// 值爲全部promise對象的值
resolve(args)
}
}
// 遍歷傳入的全部promise對象
for(let i = 0; i < args.length; i++) {
func(i, args[i])
}
})
}
複製代碼
Promise.any
靜態方法 any 會返回一個 新的 promise 對象。當 傳入的全部 promise 對象 的只要有一個狀態爲 resolved, 返回的 新的 promise 對象 的狀態變爲 resolved。 只有 全部 promise 對象 的狀態都爲 rejected, 返回的 新的 promise 對象 的狀態才爲 rejected
static any(arr) {
var args = Array.prototype.slice.call(arr)
// 返回一個新的promise對象
return new MyPromise(function(resolve, reject) {
if (args.length === 0) return resolve([])
let remain = args.length
function func(index, val) {
if (typeof val === 'object') {
// 傳入的參數爲promise對象
if (val instanceof MyPromise) {
// promise對象的狀態爲resoved, 則返回的promise對象的狀態爲resolved
// 值爲第一個狀態爲resolved的promise對象的值
if (val._status === 'resolved') {
resolve(val._value)
return false
}
// promise對象的狀態爲rejected, 緩存promise對象的值
if (val._status === 'rejected') return func(index, val._value)
// promise對象的狀態爲pending, 等promise對象的狀態變爲rejected是,緩存promise對象的值;
// 變爲resolved時, 返回的promise對象的狀態變爲resolved
val.then(resolve, (error) => {
func(index, error)
})
return true
} else if (val.then && typeof val.then === 'function') {
// 傳入的參數是thenable對象
let p = new MyPromise(val.then.bind(val))
p.then(resolve, (error) => {
func(index, error)
})
return true
}
}
// 傳入的參數是普通值
args[index] = val
// 全部的promise對象的狀態都爲rejected
if (--remain === 0) {
// 將返回的promise對象的狀態變爲rejected
// 返回的promise對象的值爲傳入的全部promise對象的值
reject(args)
}
return true
}
// 遍歷傳入的promise對象
for(let i = 0; i < args.length; i++) {
if (!func(i, args[i])) return false
}
})
}
複製代碼