Promise主要方法实现
1. Promise.all
Promise.all用于将多个Promise实例包装成一个Promise实例并返回这个Promise实例,只有所有的promise的状态变为resolved,返回的promise状态才变为resolved,否则变为rejected。
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
const arr = [...promises]
const result = []
let index = 0
function processData (i, value) {
result[i] = value
if (++index === arr.length) {
resolve(result)
}
}
for (let i = 0; i < arr.length; i++) {
const p = arr[i]
if (p && typeof p.then === 'function') {
p.then(value => {
processData(i, value)
}, reject)
} else {
processData(i, p)
}
}
})
}
2. Promise.race
返回一个promise,只要有一个状态改变了,就采用它的状态
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (const p of promises) {
if (p && typeof p.then === 'function') {
p.then(resolve, reject)
} else {
resolve(p)
}
}
})
}
// 取消一个promise的状态
function wrap (p) {
let abort
const p1 = new Promise((resolve, reject) => {
abort = reject // 通过引用把它的reject方法传递出去(闭包)
})
const p2 = Promise.race([p1, p])
p2.abort = abort
return p2
}
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 3000)
})
const p1 = wrap(p)
p1.then(res => {
console.log('success', res)
}).catch(err => {
console.log('fail', err)
})
setTimeout(() => {
p1.abort('timeout')
}, 1000)
3. Promise.prototype.finally
finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作;
finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
Promise.prototype.finally = function (callback) {
callback = typeof callback === 'function' ? callback : () => {}
return this.then(value => {
Promise.resolve(callback()).then(() => value)
}, err => {
Promise.resolve(callback()).then(() => { throw err })
})
}
const p = new Promise((resolve, reject) => {
resolve(1)
})
p.finally(() => {
hello
}).catch(err => {
console.log(err)
})
4. Promise.allSettled
Promise.allSettled()方法接受一组Promise实例作为参数,包装成一个新的Promise实例。只有等到所有这些实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束
Promise.allSettled()返回的Promise对象的状态总是fulfilled,不会变为rejected
Promise.allSettled = function (promises) {
return new Promise((resolve, reject) => {
const arr = Array.from(promises)
let index = 0
let result = []
function setData (i, value) {
result[i] = value
if (++index === arr.length) {
resolve(result)
}
}
for (let i = 0; i < arr.length; i++) {
const p = arr[i]
if (p && typeof p.then === 'function') {
p.then(value => {
setData(i, {
value,
status: 'fulfilled'
})
}, err => {
setData(i, {
reason: err,
status: 'rejected'
})
})
} else {
setData(i, {
value: p,
status: 'fulfilled'
})
}
}
})
}
const p1 = Promise.allSettled([Promise.resolve(1), 2, Promise.reject(3)])
console.log(p1)
p1.then(res => {
console.log(res)
})
5. Promise.any
ES2021引入了Promise.any()方法。该方法接收一组Promise实例作为参数,包装成一个Promise实例。只要参数实例有一个变为fulfilled,包装实例就会变成fulfilled状态;如果所有参数都变为rejected状态,包装实例就会变成rejected状态。
Promise.any = function (promises) {
return new Promise((resolve, reject) => {
let arr = Array.from(promises)
let errorResult = new Array() // AggregateError
let index = 0
function processData(i, value) {
errorResult[i] = new Error(value)
if (++index === arr.length) {
reject(errorResult) // AggregateError: All promises were rejected
}
}
for (let i = 0; i < arr.length; i++) {
const p = arr[i]
if (p && typeof p.then === 'function') {
p.then(resolve, err => {
console.log(i, err)
processData(i, err)
})
} else {
resolve(p)
}
}
})
}
Promise.any([Promise.reject(-1), Promise.reject(1), Promise.reject(-2)]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})