【Promise 源码学习】第十一篇 - Promise.all 的实现
一,前言
上一篇,主要实现了 Promise 两个实例 API(原型方法):Promise.prototype.catch
和 Promise.prototype.finally
,主要涉及以下几个点:
Promise.prototype.catch
功能测试、原理分析、源码实现;Promise.prototype.finally
功能测试、原理分析、源码实现;
本篇,继续实现 Promise 的核心静态 API(类方法):Promise.all
;
备注:Promise.all 是 Promise 中最复杂的方法;也是日常开发中的高频 API 和 面试考察点;
二,Promise.all 简介
1,API 介绍
Promise.all
功能:
批量执行 Promise,返回一个 promise 实例;
全部成功才算成功,返回全部执行结果;
有一个失败就算失败,返回第一个失败结果;
2,原生 Promise.all 功能测试
成功示例:
备注:
数字 1 不是 promise,直接被放入结果数组中;
执行结果在结果数组中的顺序与执行顺序一致;
失败示例:
备注:
第一个 promise 会先执行完,但由于第三个 promise 先失败了,所以 Promise.all 会进入 catch 并返回第一个失败的结果;
三,Promise.all 实现
1,原理分析
Promise.all
:入参是一个 promise 集合;返回一个 Promise 实例;所有 promise 的 resolve 回调结果都会被放入到一个数组;
所有 promise 都执行成功且调用 resolve 后,返回的 Promise 才调用 resolve 成功,并返回全部执行结果;
任何一个 promise 执行调用 reject 或抛出错误,返回的 Promise 就会调用 reject 失败,并返回第一个失败结果;
2,代码实现
Promise 中创建静态方法 all:
还有以下关键问题需要解决:
问题 1:如何按照执行顺序存放异步操作的返回结果?
按照异步操作执行顺序,放入 result 数字下标的对应位置;
问题 2:如何判定集合内的 promise 已经全部执行完成?
如果使用 result.length,后面异步操作如果先返回放入数组,判断 length 就不准了;
可以使用计数器,每次 promise 成功 index++,直至
index === promises.length
;
最终实现如下:
3,功能测试
执行情况分析:
Promise.all 传入待执行的 promise 集合,内部遍历执行 then 方法,普通值 1 被直接放入 result[3] = 1;(注意:如果用 result.length 判定全部完成,此时的 length 已经为 4,不准)
1 秒后,第一个 promise 执行成功,result[0] = 200;
2 秒后,第三个 promise 执行失败,执行 reject(300) 进入 then 失败处理,就会调用 Promise.all 内部 new Promise 的 reject,导致 Promise.all 返回一个失败的 promise 对象结果为 300;(注意:此时第二个 promise 已经执行但未执行完成,Promise.all 的失败不会影响它的继续执行,也无法让他停止);
3 秒后,第二个 promise 执行失败,执行 reject(400),但由于 Promise.all 已经失败,所以内部创建的 new Promise 实例已经是失败态,不能继续被改变状态;
自己实现的 Promise.all 与原生 Promise.all 表现一致;
四,结尾
本篇,主要实现 Promise 的核心静态 API(类方法):Promise.all
,主要涉及以下几个点:
测试原生 Promise.all 的使用;
Promise.all 的功能与特性分析;
Promise.all 的源码实现、执行分析、功能测试;
下一篇,继续 Promise 静态 API:Promise.race;
评论