最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Promise.all()实现根据传入url顺序, 返回按序结果

    正文概述 掘金(一筐芒果)   2021-04-16   538

    问题描述:

    • 网络请求是异步的, 如果使用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]. 这样肯定是错误的, 那之前的数据都是空的了.

    总结

    • 在使用前人, 前辈创造出来的好工具的时候, 也想想里面的原理, 这样, 才能从前辈那里学到一些知识和技能.
    • 这里需要注意的是两个点:
    1. 需要对遍历的当前对象判断是否为Promise类型, 但是, 可以使用Promise.resolve()这样可以保证当前的对象是Promise类型.
    2. 需要使用index来进行返回数据的顺序问题. res[index] = data
    3. 需要定一个count用来判断是否将所有的数据获取完毕了.

    起源地下载网 » Promise.all()实现根据传入url顺序, 返回按序结果

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元