手撕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的状态由p1p2p3决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1p2p3之中有一个被rejectedp的状态就变成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)
      })
    })
  })
}
阅读剩余
THE END