当前位置:网站首页>手写promise.all
手写promise.all
2022-06-26 17:23:00 【丹丹的小跟班】
promise.all在日常项目里经常会碰到,今天咋们手写下promise.all这个方法,并且探究下其中的细节。
先来几个demo
const demo1 = new Promise((resolve, reject) =>{
setTimeout(() => {
resolve(1)
}, 1000)
})
const demo2 = new Promise((resolve, reject) =>{
setTimeout(() => {
resolve(2)
}, 2000)
})
const demo3 = new Promise((resolve, reject) =>{
setTimeout(() => {
resolve(3)
}, 3000)
})
const demo4 = new Promise((resolve, reject) => {
setTimeout(() =>{
reslove(4)
}, 4000)
})
开始进行
第一步我们首先应该想到promise.all是可以进行链式调用的,那么内部一定返回的是一个promise对象。
function myPromiseAll(promiseArr) {
return new Promise(resolve, reject => {
···
})
}
第二步就应该对参数进行判断。任何方法最开始都应该想到,避免后期参数类型引起的其他错误。
function myPromiseAll(promiseArr) {
return new Promise(resolve, reject => {
if(Array.isArray(promiseArr)) {
······
}else {
throw new Error('请传入数组作为参数')
}
})
}
第三步我们对数组进行遍历,这个时候应该想到会不会数组里面的元素不是一个promise对象呢?可能有人就会进行if判断,可以使用instanceof 或者万能的Object.prototype.toString.call(),但其实有更简单的办法,就是直接使用Promise.resolve()包裹元素就会自动将非promise元素变成一个promise对象。
function myPromiseAll(promiseArr) {
return new Promise(resolve, reject => {
if(Array.isArray(promiseArr)) {
const len = promiseArr.length
for(let i = 0; i < len; i ++) {
Promise.resolve(promiseArr[i]).then(res => {
······
}).catch(err => {
reject(err)
})
}
}else {
throw new Error('请传入数组作为参数')
}
})
}
第四步,根据返回的结果是一个数组我们就应该想到需要创建一个数组进行结果保存。这个时候就会出现最容易犯错的地方,那就是数组顺序,我们会发现官方的promise.all返回的数组元素里面的顺序是传入的promise数组参数的顺序。直接push可能会因为执行时间的不同从而push进结果数组的时机不同,这个时候就需要使用数组下标的方式来进行赋值,最后在判断什么时候结束判断,那就是结果数组长度等于参数的时候。
function myPromiseAll(promiseArr) {
return new Promise((resolve, reject) => {
if(Array.isArray(promiseArr)) {
const len = promiseArr.length
let resArr = []
for(let i = 0; i < len; i ++) {
Promise.resolve(promiseArr[i]).then(res => {
resArr[i] = res
if(resArr.length === len) {
resolve(resArr)
}
}).catch(err => {
reject(err)
})
}
}else {
throw new Error('请传入数组作为参数')
}
})
}
第五步,大家觉得这样就结束了?如果大家测试就会发现,上面的promise.all方法执行myPromiseAll([demo1, demo2, demo3, demo4])那是没有丝毫问题的,但是这个参数顺序是根据递增的顺序变化的,也就是说他们执行的顺序和参数顺序是一致的,如果我们置换顺序,比如demo4, demo1, demo2, demo3就会发现该数组的第一个结果竟然是空(empty),也就是说返回的结果是一个稀缺数组。那是因为第一个参数定时时间最长,所以会在最后执行,当执行到demo3的时候,i就已经等于3了,而数组使用下标进行赋值时,会改变数组的长度,尽管有时候下标的值是空(empty),所以就执行了resolve,但这是demo4并没有执行,所以会造成结果的缺失。这个时候我们就需要一个中间数字来记录我们执行了几个参数。
function myPromiseAll(promiseArr) {
return new Promise((resolve, reject) => {
if(Array.isArray(promiseArr)) {
const len = promiseArr.length
let resArr = []
let num = 0
for(let i = 0; i < len; i ++) {
Promise.resolve(promiseArr[i]).then(res => {
num ++
resArr[i] = res
if(num === len) {
resolve(resArr)
}
}).catch(err => {
reject(err)
})
}
}else {
throw new Error('请传入数组作为参数')
}
})
}
最后大功告成!
注意点总结:
- 注意参数的类型
- 注意参数数组里面的元素可以不为promise对象
- 注意成功是返回的结果顺序
边栏推荐
- Prometeus 2.34.0 new features
- Leetcode topic [array] -283- move zero
- 类型多样的石膏PBR多通道贴图素材,速来收藏!
- Leetcode HOT100 (22--- bracket generation)
- Leetcode - 226. Retourner l'arbre binaire (bfs)
- 背包问题求方案数
- 牛客网:设计LRU缓存结构 设计LFU缓存结构
- Introduction to minimal API
- Jouer avec Linux et installer et configurer MySQL facilement
- Programmer interview guide - self introduction
猜你喜欢

Which low code platform is more friendly to Xiaobai? Here comes the professional evaluation!

Leetcode HOT100 (22--- bracket generation)

分布式架构概述

宝藏又小众的CTA动画素材素材网站分享

分布式缓存/缓存集群简介

Classical synchronization problem

The high concurrency system is easy to play, and Alibaba's new 100 million level concurrent design quick notes are really fragrant

【推荐系统学习】推荐系统架构

20:第三章:开发通行证服务:3:在程序中,打通redis服务器;(仅仅是打通redis服务器,不涉及具体的业务开发)
Teach you to learn dapr - 6 Publish subscription
随机推荐
The difference between round and truncate in SQL (round or truncate)
Discover K8E: minimalist kubernetes distribution
Detailed contract quantification system development scheme and technical description of quantitative contract system development
Live broadcast preview | how can programmers improve R & D efficiency? On the evening of June 21, the video number and station B will broadcast live at the same time. See you or leave!
Teach you to learn dapr - 9 Observability
QPushButton 样式使用示例(以及按钮setmenu添加下拉菜单的方法)
sql中ROUND和TRUNCATE的区别(四舍五入还是截取小数点后几位)
Leetcode daily [2022 - 02 - 16]
分布式缓存/缓存集群简介
Secrets of gear contract
Interpretation of new plug-ins | how to enhance authentication capability with forward auth
Leetcode HOT100 (22--- bracket generation)
MySQL add column failed because there was data before, not null by default
Environment setup mongodb
Microservice architecture practice: user login and account switching design, order query design of the mall
Getting started with mongodb
Programmer interview guide - self introduction
Alibaba's "high concurrency" tutorial "basic + actual combat + source code + interview + Architecture" is a god class
Platform management background and merchant menu resource management: merchant registration management design
halcon之区域:多种区域(Region)特征(5)