微信小程序多图片上传实用代码记录
由于在小程序中,wx.uploadFile 只能一次上传一张图片,因此在一次需要上传多张图片的应用场景中例如商品图片上传、评论图片上传等场景下,不得不使用for等循环上传每一张图片,多次调用wx.uploadFile,由此引发了ajax的闭包问题。
初始代码
submit() {
let tmparr = null;
let _that = this;
for (var k = 0; k < this.data.judgedetaillist.length; k++) {
let _k = k;
//图片上传
this.data.fileList[_k].forEach((item) => {
wx.uploadFile({ //这里一定要用 wx.uploadFile 否则无法穿到后台
filePath: item.url, //你要上传的路径
name: 'file', //你上传到后台的name值
async: false, //设置为同步
formData:{ // 如果你要验证你的token 可以用formData来给后台传值
path:"judge"
},
url: 上传地址,
success(res){
let img = JSON.parse(res.data);
//录入到list
if(img.err=='success' && img.c_url!=null && img.c_url!=undefined)
{
if(_that.data.judgedetaillist[_k].fileList.length==0 || _that.data.judgedetaillist[_k].fileList==null || _that.data.judgedetaillist[_k].fileList==undefined){
_that.data.judgedetaillist[_k].fileList=[];
}
_that.data.judgedetaillist[_k].fileList.push({url:img.c_url});
_that.setData({
judgedetaillist:_that.data.judgedetaillist
})
}
}
})
})
}
console.log(JSON.stringify(this.data.judgedetaillist));
return false;
}
代码问题
我这代码的设想是,
遍历储存上传文件的 fileList数组-》wx.uploadFile上传到服务器-》返回服务器路径-》将返回的路径传送到 judgedetaillist.fileList中-》judgedetaillist传输到后台新增评论
这个代码执行下来会出现问题,即在 wx.uploadFile后获取了对应的url存储到judgedetaillist中后
console.log(JSON.stringify(this.data.judgedetaillist));
会出现
fileList":[]
但是
如果打印
console.log(this.data.judgedetaillist);
会出现
fileList: Array(1)
0:
url: “/upload/judge/16654684.png”
proto: Object
length: 1
nv_length: (…)
proto: Array(0)
在预设的对象中又能读取到数据,此时再打印
console.log(this.data.judgedetaillist[0].fileList.length);
发现明明数组中有对象,但是这个对象根本取不到,并且连length都无法读取
原因剖析
由于wx.uploadFile默认是使用异步,因此在不断的for循环中,它返回的值并不是同步的,导致多个同时执行,此时数组使用的是地址引用,并没有实际赋值成功,赋值的数组已经被修改了,因为原来的长度是0,所以获取不到数组,但又包含修改后的结果。
要解决这个bug就是让wx.uploadFile可以同步执行,需要用到
1、new Promise
2、async,await
3、取消forEach, forEach 中使用 async/await 时,异步操作并不会等待前一个操作结束再执行下一个,而是会同时执行多个异步操作
解决方案(非生产环境代码)
本来h5中的多图片上传是直接使用 async:false就可以,但是在微信中这是无效的。所以代码写成这样
解决方案一
使用new Promise,配合async,await进行多次循环
//图片上传函数
Upload: function (uploadFile) {
return new Promise((resolve, reject) => {
wx.uploadFile({ //这里一定要用 wx.uploadFile 否则无法穿到后台
filePath: uploadFile, //你要上传的路径
name: 'file', //你上传到后台的name值
formData: { // 如果你要验证你的token 可以用formData来给后台传值
path: "judge"
},
url: 上传路径,
success: (res) => {
// 上传完成操作
const data = JSON.parse(res.data)
resolve({
data: data
})
},
fail: (err) => {
//上传失败:修改pedding为reject
wx.showToast({
title: "网络出错,上传失败",
icon: 'none',
duration: 1000
});
reject(err)
}
});
})
},
//接收返回的路径,关键是async ,await
async submit() {
let tmparr = null;
for (var k = 0; k < this.data.judgedetaillist.length; k++) {
let _k = k;
//图片上传
for (let i = 0; i < this.data.fileList[_k].length; i++) {
tmparr =await this.Upload(this.data.fileList[_k][i].url);
if(this.data.judgedetaillist[_k].fileList==null || this.data.judgedetaillist[_k].fileList==undefined){
this.data.judgedetaillist[_k].fileList=[];
}
this.data.judgedetaillist[_k].fileList.push({ url: tmparr.data.c_url });
this.setData({
judgedetaillist: this.data.judgedetaillist
})
}
}
console.log(JSON.stringify(this.data.judgedetaillist));
}
解决方案二
利用Promise.all,当所有的异步请求成功后才会执行,将全部异步执行完后的数据一次性返回
调用测试
console.log(this.uploadImage(this.data.fileList[_k]))
返回结果
Promise {}
proto: Promise
[[PromiseState]]: “fulfilled”
[[PromiseResult]]: Array(3)
0: “/upload/judge/1691391628202skmda.png”
1: “/upload/judge/1691391628219ttxps.png”
2: “/upload/judge/1691391628227yehwf.png”
length: 3
nv_length: (…)
proto: Array(0)
利用这个可以一次性获取全部的结果文章来源:https://www.toymoban.com/news/detail-639258.html
代码示例:文章来源地址https://www.toymoban.com/news/detail-639258.html
uploadImage: function(tempFilePaths){
return new Promise((presolve,preject)=>{
if({}.toString.call(tempFilePaths)!='[object Array]'){
throw new TypeError(`上传图片参数 tempFilePaths 类型错误!`)
}
//路径数组为空时 不上传
if(tempFilePaths.length==0){
presolve([])
return
}
let uploads = []
tempFilePaths.forEach((item,i)=>{
uploads[i] = new Promise ((resolve)=>{
console.log(item);
wx.uploadFile({ //这里一定要用 wx.uploadFile 否则无法穿到后台
filePath: item.url, //你要上传的路径
name: 'file', //你上传到后台的name值
formData: { // 如果你要验证你的token 可以用formData来给后台传值
path: "judge"
},
url: 你的上传路径,
success(res){
console.log(res);
resolve(JSON.parse(res.data).c_url)
},
fail(err){
console.log(err)
}
})
})
})
Promise.all(uploads).then(res=>{
//图片上传完成
presolve(res)
}).catch(err=>{
preject(err)
wx.showToast({
title:'上传失败请重试',
icon:'none'
})
})
})
},
到了这里,关于微信小程序多图片上传实用代码记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!