理解 Promise.all 和 Promise.race 的实现
Promise.all
首先我们从一个正常的例子来看拆解一下 Promise.all
拆解Promise.all
- 我们能知道
all方法接受一个数组作为参数,具体来说应该是具有Iterator接口的数据。 - 根据
Promise.all的特性还能知道,Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。言外之意,如果不是 Promise 就会先调用Promise.resolve方法,将参数转为Promise实例,再进一步处理。 - 如果参数实例的状态
全部变成fulfilled,结果的状态才会变成fulfilled,此时各个参数的返回值组成一个数组,传递给结果的then的回调函数。 - 参数实例中有一个被
rejected,结果的状态就变成rejected,此时第一个被reject的实例的返回值,结果会传递给catch的回调函数。
我们根据上述的拆解,来进行一下代码的实现:
1 | |
我们使用测试用例验证一下这个方法能不能用,首先模拟一个延迟函数,delay,然后再定义两个方法 delay1,delay2。
1 | |
1 | |
调用,按照预期的话应该是打印出来两个数据。
1 | |
最后我们能发现确实已经可以返回两个延迟函数中的数据。
Promise.race
还是根据其特性来实现,首先 race 的方法和 all 的基础性都是一样的,接受的参数以及类别等,其用法是多个实例中有一个实例率先改变状态,总结果的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给结果集的回调函数。
拆解Promise.race
- 首先基本和
all的类似,然后由其特性可知,其实内部实现应该是谁先完成就谁返回,也就是循环体内部只要有一个成功执行完毕就可以resolve。
我们来看一下具体实现:
1 | |
race 最常见的一个场景就是,如果页面里有需要请求的接口,但是接口耗时如果比较长,这个时候可以利用 race 配合 delay 函数做一个兜底,发请求的同时开一个多少 ms 的定时器,如果定时器结束之前接口还没有响应的话则中断请求立即返回,而不至于接口一直处于 pedding 挂起状态。那我们可以根据这个例子验证一下 race 是否可以用。
我们这次修改一下两个延迟函数,
1 | |
按照预期的话,data 的打印应该是延迟比较小的那个,因为先执行完成先返回了。
1 | |
由此可见我们的 race 通过用例验证也是可行的。
至此两个比较常用的 promise 的方法我们就实现了,其实很多东西从使用的角度上来看,内部实现原理大概都是能比较清楚的,所以我们就应该注意更多的细节,例如边界条件、类型包装、代码执行的位置等。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!