问题描述:
- 网络请求是异步的, 如果使用
for
循环, 进行好多的数据请求, 返回的数据, 很可能不是按照用户输入的顺序返回的.
解决方法:
- 这里可以使用
Promise.all()
方法实现, 异步网络请求, 返回的数据也是按序的.
export default functionlaodFiles(dataFiles) {
return new Promise(((resolve, reject) => {
// promise.all保证了, 输出的顺序和输入的是一致的
Promise.all(dataFiles.map(dataFile => {
axios.get(dataFile.url).then(res => ({date: new Date(res), data: res}))
})).then(data => {
resolve(data)
}).catch(err => {
reject(err)
})
}))
}
实现原理
Promise.all
内部是怎么实现按序的呢, 下面我们就来扒一扒Promise.all
内部的秘密- 首先贴上, 手写的
Promise.all()
正确写法:
function PromiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new Error('传入的参数必须得是数组格式'))
}
let res = []
let count;
promises.forEach((promise, index) => {
// 这里其实需要判断一下, 当前遍历的promise是否是Promise类型, 但是, 这里没有判断, 想想是因为什么原因.
Promise.resolve(promise).then(data => {
// 注意点1: index用来保证按序存储
res[index] = data
count++
// 注意点2: count用来保证获取到了想要的所有数据
if(count === promises.length) {
resolve(res)
}
}, err => {
}).catch(err => {
return reject(err)
})
})
})
}
不正确的写法一:
- 上面代码的
forEach
方法中, 第一个参数promise
遍历的当前对象, 后一个index
是关键, 可能会有人在处理结果的时候, 像下面这样书写:
let count =0
let res = []
let length= promises.length
promises.forEach(promise => {
Promise.resolve(promise).then(data => {
res.push(data)
// 直接判断判断当前的结果数组长度是否是传入的数组长度
if(res.length === length) resolve(res)
})
})
-
但是像这样直接用返回结果长度会有一个问题, 那就是, 里面的结果数据不是按序的, 只要结果返回就往里面
push
,可能第一个返回的结果, 并不是第一个传入参数对应的, 可能是第三个或者任何一个.
不正确的写法二:
-
- 上面代码的
forEach
方法中, 第一个参数promise
遍历的当前对象, 后一个index
是关键, 那你说index
是关键, 那我就带上就好了 , 然后,可能会有人在处理结果的时候, 像下面这样书写:
- 上面代码的
let count =0
let res = []
let length= promises.length
promises.forEach((promise, index) => {
Promise.resolve(promise).then(data => {
// 1.根据返回的结果, 将数据按照对应的index放进数组, 就可以保证按序了
res[index] = data
// 2.直接判断判断当前的结果数组长度是否是传入的数组长度(这里有坑
if(res.length === length) resolve(res)
})
})
- 那你可能会说, 我带了
inded
也按序了, 我这样写就没问题了吧! 但是! 你想想看, 如果, 第一个返回的就是, 最后一个index
, 那直接把数组装满了, 结果为:[undefined,undefined,undefined,undefined,......, data]
. 这样肯定是错误的, 那之前的数据都是空的了.
总结
- 在使用前人, 前辈创造出来的好工具的时候, 也想想里面的原理, 这样, 才能从前辈那里学到一些知识和技能.
- 这里需要注意的是两个点:
- 需要对遍历的当前对象判断是否为
Promise
类型, 但是, 可以使用Promise.resolve()
这样可以保证当前的对象是Promise
类型. - 需要使用
index
来进行返回数据的顺序问题. res[index] = data - 需要定一个
count
用来判断是否将所有的数据获取完毕了.
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!