多文件上传时的异步转同步

技术概述

微信小程序要上传多图,并让多个上传进程最后保持同步返回结果,也适用于各种文件的上传

技术详述

上传一张图片

上传一张图片到微信存储需要先获取文件的后缀名,才能在云端读取时不出错

    let item = this.data.pic;//图片的暂存地址
    let suffix = /\.\w+$/.exec(item)[0];//正则表达式返回文件的扩展名,可以参考各种正则教程
    wx.cloud.uploadFile({
        cloudPath: new Date().getTime()+suffix, // 上传至云端的路径
        filePath: item,
        success: res=>{
        wx.showToast({
            title: "上传成功",//弹出提示
        })
        this.setData({
            pic:res.fileID //将返回值中的文件在云端的id赋值给data中的数据
        })
        },
        fail: res=>{
        wx.showToast({
            title: "上传失败",//弹出提示
        })
        }
    })

上传多张图片

可以很自然的想到,如果我们要上传多张图片,那么就将以上过程放入for循环就行了,但是如果只是单纯的使用for循环,会导致上传顺序出错,并且无法确保所有图片都上传成功,所以要使用promise.all()来执行一系列异步操作并返回一个正确顺序的结果集。

wx.showLoading({
        title: '正在上传',//在上传开始后,将出现loading幕布,确保用户不会误操作
        mask:true
    })
let promiseArr = [];//存放promise的集合
for (let index = 0; index < this.data.picBox.length; index++) {
    promiseArr.push(new Promise((reslove,reject)=>{
    let item = this.data.picBox[index];
    let suffix = /\.\w+$/.exec(item)[0];//正则表达式返回文件的扩展名
    wx.cloud.uploadFile({
        cloudPath: new Date().getTime() + index +suffix, // 上传至云端的路径,加上index是为了防止执行时间同步造成图片覆盖
        filePath: item,
        success: res=>{
        this.setData({
            picId:this.data.picId.concat(res.fileID)//数组连接
        })
        reslove('成功');//执行成功,返回一个状态为“成功”的promise对象
        },
        fail: res=>{
        wx.hideLoading();
        wx.showToast({
            title: "上传失败",
        })
        reject('失败');//异步调用失败,只要有一个失败整个系列的异步过程就都失败了,返回一个状态为“失败”的对象
        }
    })
    }))
}
Promise.all(promiseArr).then(res=>{//返回值将会按照参数内的promise 顺序排列,而不是由调用 promise 的完成顺序决定
    console.log(res);
    //res中存放的是每个promise对象的结果集,失败则是第一个失败promise对象的结果集
    wx.hideLoading();
    wx.showToast({
    title: "上传成功",
    })

如果上传成功五张图片,则打印出的res是

技术使用中遇到的问题和解决过程。

遇到的问题:上传时如果以时间戳作为文件名可能会出现两个promise调用的时间相同,导致文件名相同而产生覆盖。
解决过程:为每个文件名的末尾加上它的独特编号

cloudPath: new Date().getTime() + index +suffix

总结

Promise.all(iterable)方法返回一个 [Promise],此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。promise风格调用极大程度的便利了回调函数的阅读,也让异步操作的同步变得更加简单,非常值得学习

参考博客

JavaScript - promise.all()及实现
Promise初步详解(resolve,reject,catch)
微信小程序之上传多张图片(云开发)

posted @ 2021-06-26 15:18  spiritcsk  阅读(402)  评论(0编辑  收藏  举报