手撕promise.all .any .race
Promise.resolve
-
Promise.resolve
最终结果还是一个Promise
,并且与Promise.resolve(该值)
传入的值息息相关 -
传入的参数可以是一个
Promise实例
,那么该函数执行的结果是直接将实例返回 -
这里最主要需要理解跟随,可以理解成
Promise最终状态
就是这个thenable对象输出的值
Promise.myResolve = function (value) {
// 是Promise实例,直接返回即可
if (value && typeof value === 'object' && (value instanceof Promise)) {
return value
}
// 否则其他情况一律再通过Promise包装一下
return new Promise((resolve) => {
resolve(value)
})
}
// 测试一下,还是用刚才的例子
// 1. 非Promise对象,非thenable对象
Promise.myResolve(1).then(console.log) // 1
// 2. Promise对象成功状态
const p2 = new Promise((resolve) => resolve(2))
Promise.myResolve(p2).then(console.log) // 2
// 3. Promise对象失败状态
const p3 = new Promise((_, reject) => reject('err3'))
Promise.myResolve(p3).catch(console.error) // err3
Promise.reject
Promise.reject()
方法返回一个带有拒绝原因的Promise
对象。
Promise.myReject = function (value) {
return new Promise((_, reject) => {
reject(value)
})
}
// 测试一下
Promise.myReject(new Error('fail'))
.then(() => console.log('Resolved'),
(err) => console.log('Rejected', err))
// Rejected Error: fail
// at <anonymous>:9:18
Promise.all
Promise.all()
方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.all([p1, p2, p3])
最终p
的状态由p1
、p2
、p3
决定,分成两种情况。
(1)只有p1
、p2
、p3
的状态都变成fulfilled
,p
的状态才会变成fulfilled
,此时p1
、p2
、p3
的返回值组成一个数组,传递给p
的回调函数。
(2)只要p1
、p2
、p3
之中有一个被rejected
,p
的状态就变成rejected
,此时第一个被reject
的实例的返回值,会传递给p
的回调函数。
Promise.all
接受一个数组,返回值是一个新的 Promise
实例
Promise.MyAll = function (promises) {
return new Promise((resolve, reject) => {
})
}
Promise
实例都成功,Promise.all
才成功。不难想到,咱得需要一个数组来收集这些 Promise
实例的 resolve
结果。但有句俗话说得好:“不怕一万,就怕万一”,万一数组里面有元素不是 Promise
咋办 —— 那就得用 Promise.resolve()
把它办了。这里还有一个问题,Promise
实例是不能直接调用 resolve
方法的,咱得在 .then()
中去收集结果。将收集到的结果(数组arr
)作为参数传给外层的 resolve
方法。用计数器==promises.length判断所有的实例收集成功与否
Promise.MyAll = function (promises) {
let arr = [],
count = 0
return new Promise((resolve, reject) => {
promises.forEach((item, i) => {
Promise.resolve(item).then(res => {
arr[i] = res
count += 1
if (count === promises.length) resolve(arr)
})
})
})
}
最后再.catch()或.then()中传入第二个参数来捕获失败
Promise.MyAll = function (promises) {
let arr = [],//收集promises案例的resolve结果
count = 0//计数器
return new Promise((resolve, reject) => {
promises.forEach((item, i) => {
Promise.resolve(item).then(res => {//把非promise的对象转为promise
arr[i] = res
count += 1
if (count === promises.length) resolve(arr)//都成功下调用resolve
}).catch(reject)
})
})
}
//then方法
Promise.MyAll = function (promises) {
let arr = [],
count = 0
return new Promise((resolve, reject) => {
promises.forEach((item, i) => {
Promise.resolve(item).then(res => {
arr[i] = res
count += 1
if (count === promises.length) resolve(arr)
}, reject)
})
})
}
测试案例
const p1 = Promise.resolve('p1')
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p2 延时一秒')
}, 1000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p3 延时两秒')
}, 2000)
})
const p4 = Promise.reject('p4 rejected')
const p5 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('p5 rejected 延时1.5秒')
}, 1500)
})
// 所有 Promsie 都成功
Promise.MyAll([p1, p2, p3])
.then(res => console.log(res))
.catch(err => console.log(err)) // 2秒后打印 [ 'p1', 'p2 延时一秒', 'p3 延时两秒' ]
// 一个 Promise 失败
Promise.MyAll([p1, p2, p4])
.then(res => console.log(res))
.catch(err => console.log(err)) // p4 rejected
// 一个延时失败的 Promise
Promise.MyAll([p1, p2, p5])
.then(res => console.log(res))
.catch(err => console.log(err)) // 1.5秒后打印 p5 rejected 延时1.5秒
// 两个失败的 Promise
Promise.MyAll([p1, p4, p5])
.then(res => console.log(res))
.catch(err => console.log(err)) // p4 rejected
Promise.race
以状态变化最快的那个 Promise
实例为准,最快的 Promise
成功 Promise.race
就成功,最快的 Promise
失败 Promise.race
就失败。
Promise.myRace = (promises) => {
return new Promise((rs, rj) => {
promises.forEach((p) => {
// 对p进行一次包装,防止非Promise对象
// 并且对齐进行监听,将我们自己返回的Promise的resolve,reject传递给p,哪个先改变状态,我们返回的Promise也将会是什么状态
Promise.resolve(p).then(rs).catch(rj)
})
})
}
// 测试一下
const p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 1)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 2)
})
Promise.myRace([p1, p2]).then((value) => {
console.log(value) // 2
})
Promise.myRace([p1, p2, 3]).then((value) => {
console.log(value) // 3
})
参考
https://juejin.cn/post/7038371452084551694#heading-9
https://juejin.cn/post/7069805387490263047
手写尝试:
Promise.myall=(promises)=>{
let arr[]
let count=0
return new Promise((resolve,reject)=>{
promises.foreach(item,i)=>{
Promise.resolve(item).then((res)=>{
arr[i]=res;
count++;
if(count===promises.length) resolve(arr)
}).catch((reject)=>{console.log(reject)})
)
}
}
)
}
promise.any
function myPromiseAny(promises) {
return new Promise((resolve, reject) => {
let results = []
promises.forEach(promise => {
promise.then(resolve, err => {
results.push(err)
if (results.length === promises.length) reject(results)
})
})
})
}