前言
上次我們手寫了一個promise罩润,相信大家已經(jīng)對 Promise 有了深度的理解热某,這次我們再把 Promise 的所有相關(guān)方法都實現(xiàn)一下计济。
Promise.prototype.catch
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected)
}
catch 方法相對簡單饭入,就是調(diào)用 promise 自身的 then 方法嘹悼,只傳入失敗的回調(diào)叛甫。因為 then 方法本身具有值的傳遞性,所以我們只需傳入失敗的回調(diào)即可杨伙,即使沒有成功的回調(diào)其监,也會將值自動的傳遞下去。
Promise.prototype.finally
無論成功還是失敗都會執(zhí)行 finally
Promise.prototype.finally = function(onFinished) {
return this.then(val => {
onFinished()
return val
}).catch((err) => {
onFinished()
return err
})
}
finally 需要注意
finally 的回調(diào)沒有參數(shù)
promise 如果成功限匣,則將成功的值正常傳遞下去抖苦,不會因 finally 而斷掉,舉例:
promise 如果失敗,同上
Promise
.resolve(1)
.finally(val => console.log(val)) // undefind
.then(val => console.log(val)) // 1
Promise
.reject('error')
.finally(val => console.log(val)) // undefind
.catch(err => console.log(err)) // error
Promise.resolve
返回一個成功的 promise
Promise.resolve = function(val) {
return new Promise(resolve => {
resolve(val)
})
}
emmm 一眼就懂
Promise.reject
返回一個失敗的 promise
Promise.reject = function(val) {
return new Promise((resolve, reject) => {
reject(val)
})
}
啥也不說了锌历。贮庞。。
Promise.all
返回一個 promise 實例究西。接受一個可迭代的對象窗慎,會等 iterable 參數(shù)內(nèi)所有的 promise 都 resolved 時被 reslove,如果有一個 rejected卤材,則此實例被 reject遮斥。
如果 iterable 沒有 promise,則此實例直接被 resolve扇丛。
返回值是一個數(shù)組术吗,數(shù)組的值按照 iterable 的迭代順序排列。
Promise.all = function(ps) {
let resolve
let reject
const promise = new Promise((r, j) => {
resolve = r
reject = j
})
let fufilledCount = 0
let index = 0;
const ret = [];
const wrapFufilled = i => {
return val => {
fufilledCount += 1
ret[i] = val
if (fufilledCount >= index) {
resolve(ret)
}
}
}
const wrapRejected = i => {
return err => {
reject(err)
}
}
for (let p of ps) {
Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))
index += 1
}
return promise
}
注意幾個要點
因為接受的是一個可迭代對象(iterable)帆精,所以我們用 for of 遍歷较屿。
這里我們用 Promise.resolve() 包裝一下所有的 promise。
wrapFufilled 的目的是為了記錄當前遍歷的 index实幕。
Promise.race
返回一個 promise吝镣,一旦迭代器中的某個promise解決或拒絕,返回的 promise就會解決或拒絕昆庇。
Promise.race = function(ps) {
let resolve
let reject
const promise = new Promise((r, j) => {
resolve = r
reject = j
})
for (let p of ps) {
Promise.resolve(p).then(
val => resolve(val),
err => reject(err)
)
}
return promise
}
Promise.any
只要其中的一個 promise 成功末贾,就返回那個已經(jīng)成功的 promise 。如果可迭代對象中沒有一個 promise 成功(即所有的 promises 都失敗/拒絕)整吆,就返回一個失敗的 promise 和AggregateError類型的實例拱撵,它是 Error 的一個子類,用于把單一的錯誤集合在一起表蝙。
本質(zhì)上拴测,這個方法和Promise.all()是相反的
Promise.any = function(ps) {
let resolve
let reject
const promise = new Promise((r, j) => {
resolve = r
reject = j
})
let errCount = 0
let pCount = 0
for (let p of ps) {
pCount += 1
Promise.resolve(p).then(
val => resolve(val),
err => {
errCount += 1
if (errCount >= pCount) {
reject(new AggregateError('All promises were rejected'))
}
}
)
}
return promise
}
Promise.allSettled
返回一個在所有給定的promise都已經(jīng)fulfilled或rejected后的promise,并帶有一個對象數(shù)組府蛇,每個對象表示對應(yīng)的promise結(jié)果集索。
這里舉一個例子:
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).
then((results) => results.forEach((result) => console.log(result)));
// 輸出結(jié)果
// Object { status: "fulfilled", value: 3 }
// Object { status: "rejected", reason: "foo" }
具體實現(xiàn):
Promise.allSettled = function(ps) {
let resolve
let reject
const promise = new Promise((r, j) => {
resolve = r
reject = j
})
let finishedCount = 0
let index = 0;
const ret = [];
const wrapFufilled = i => {
return val => {
finishedCount += 1
ret[i] = {
status: 'fufilled',
value: val
}
if (finishedCount >= index) {
resolve(ret)
}
}
}
const wrapRejected = i => {
return err => {
finishedCount += 1
ret[i] = {
status: 'rejected',
value: err
}
if (finishedCount >= index) {
resolve(ret)
}
}
}
for (let p of ps) {
Promise.resolve(p).then(wrapFufilled(index), wrapRejected(index))
index += 1
}
return promise
}