• 手写Promise.all/race/any/settled方法


    Promise.all

            Promise.all 的返回值是一个新的 Promise 实例。

            Promise.all 接受一个可遍历的数据容器,容器中每个元素都应是 Promise 实例。咱就是说,假设这个容器就是数组

            数组中每个 Promise 实例都成功时(由pendding状态转化为fulfilled状态),Promise.all 才成功。这些 Promise 实例所有的 resolve 结果回按原来的顺序集合在一个数组中作为 Promise.all 的 resolve 的结果。

            数组中只要有一个 Promise 实例失败(由pendding状态转化为rejected状态),Promise.all 就失败。Promise.all 的 .catch() 会捕获到这个 reject。

    1. let p1 = new Promise((res, rej) => {
    2. res('p-1')
    3. })
    4. let p2 = new Promise((res, rej) => {
    5. setTimeout(() => {
    6. res('p-2')
    7. }, 1000)
    8. })
    9. Promise.all([p1, p2])
    10. .then((res => {
    11. console.log(res)
    12. }))
    13. .catch(err => {
    14. console.log(err)
    15. })
    16. // ['p-1', 'p-2']

           1、 如此,需要返回一个Promise对象

    1. Promise.myAll = function (promises) {
    2. return new Promise((resolve, reject) => {
    3. })
    4. }

           2、返回的是一个数组,并且顺序可能出现混乱,所以还需要一个计数器

    1. Promise.myAll = function (promises) {
    2. let arr = []
    3. let count = 0
    4. return new Promise((resolve, reject) => {
    5. promises.forEach((item, i) => {
    6. Promise.resolve(item)
    7. .then(res => {
    8. arr[i] = res
    9. count++ // 当count的和传入数组长度相同的时候说明全部为成功
    10. if (count == promises.length) resolve(arr)
    11. })
    12. .catch(reject)
    13. });
    14. })
    15. }

    验证一下

    1. Promise.myAll([p1, p2])
    2. .then(res => {
    3. console.log('meRes:', res)
    4. })
    5. .catch(err => {
    6. console.log('myErr:', err)
    7. })

    没啥问题

    看看错误的情况,加一个返回失败的p3

    1. let p3 = new Promise((res, rej) => {
    2. rej('p-3')
    3. })
    4. Promise.myAll([p1, p2, p3])
    5. .then(res => {
    6. console.log('meRes:', res)
    7. })
    8. .catch(err => {
    9. console.log('myErr:', err)
    10. })

     

    ok  了解了Promise.all的原理 同理得Promise.race

    Promise.race

            最快改变状态的Promise

    1. Promise.myRace = function (promises) {
    2. return new Promise((resolve, reject) => {
    3. promises.forEach(item => {
    4. Promise.resolve(item)
    5. .then(res => {
    6. resolve(res)
    7. })
    8. .catch(reject)
    9. })
    10. })
    11. }

     

    Promise.any

            有一个成功即为成功 全部失败则为失败

    1. // 正好和promise.all相反
    2. Promise.myAny = function (promises) {
    3. let arr = []
    4. let count = 0
    5. return new Promise((resolve, reject) => {
    6. promises.forEach((item, i) => {
    7. Promise.resolve(item)
    8. .then(res => {
    9. resolve(res)
    10. })
    11. .catch(err => {
    12. arr[i] = err
    13. count++
    14. if (count == promises.length) reject(new Error('All promises were rejected'))
    15. })
    16. })
    17. })
    18. }

    Promise.allSettled

            所有结果无论成功与否都会收集起来

            先看下Promise.allSettled的运行结果

    1. let p1 = new Promise((res, rej) => {
    2. res('p-1')
    3. })
    4. let p2 = new Promise((res, rej) => {
    5. setTimeout(() => {
    6. res('p-2')
    7. }, 1000)
    8. })
    9. let p3 = new Promise((res, rej) => {
    10. rej('p-3')
    11. })
    12. Promise.allSettled([p1, p2, p3])
    13. .then(res=>{
    14. console.log(res)
    15. })

     返回的是一个数组,status标记状态,成功和失败分别将结果放在value和reason中

            因为要将所有状态返回,所以无论成功还是失败的都需要将计数器加一

    1. Promise.myAllSettled = function (promises) {
    2. let arr = []
    3. let count = 0
    4. return new Promise((resolve, reject) => {
    5. promises.forEach((item, i) => {
    6. Promise.resolve(item)
    7. .then(res => {
    8. arr[i] = { status: 'fulfilled', value: res }
    9. count++
    10. if (count == promises.length) resolve(arr)
    11. })
    12. .catch(err => {
    13. arr[i] = { status: 'rejected', reason: err }
    14. count++
    15. if (count == promises.length) resolve(arr)
    16. })
    17. })
    18. })
    19. }

  • 相关阅读:
    leetCode 76. 最小覆盖子串 + 滑动窗口 + 图解(详细)
    cesium 三维坐标系绘制
    深度学习入门(二十六)卷积神经网络——池化层
    快速搭建Jenkins自动化集成cicd工具
    Nginx环境搭建及前端部署教程(Windows版)
    VMwareWorkStation如何添加万兆网卡,万兆网卡添加教程
    亚马逊关键词搜索API接口(item_search-按关键字搜索亚马逊商品接口),亚马逊API接口
    38 方法区的演进细节
    基于Go加载shellcode
    进程间通信-内存映射二
  • 原文地址:https://blog.csdn.net/zjw0021/article/details/126091195