微信小程序多圖片上傳實(shí)用代碼記錄
由于在小程序中,wx.uploadFile 只能一次上傳一張圖片,因此在一次需要上傳多張圖片的應(yīng)用場景中例如商品圖片上傳、評論圖片上傳等場景下,不得不使用for等循環(huán)上傳每一張圖片,多次調(diào)用wx.uploadFile,由此引發(fā)了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, //設(shè)置為同步
formData:{ // 如果你要驗(yàn)證你的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;
}
代碼問題
我這代碼的設(shè)想是,
遍歷儲存上傳文件的 fileList數(shù)組-》wx.uploadFile上傳到服務(wù)器-》返回服務(wù)器路徑-》將返回的路徑傳送到 judgedetaillist.fileList中-》judgedetaillist傳輸?shù)胶笈_新增評論
這個(gè)代碼執(zhí)行下來會出現(xiàn)問題,即在 wx.uploadFile后獲取了對應(yīng)的url存儲到j(luò)udgedetaillist中后
console.log(JSON.stringify(this.data.judgedetaillist));
會出現(xiàn)
fileList":[]
但是
如果打印
console.log(this.data.judgedetaillist);
會出現(xiàn)
fileList: Array(1)
0:
url: “/upload/judge/16654684.png”
proto: Object
length: 1
nv_length: (…)
proto: Array(0)
在預(yù)設(shè)的對象中又能讀取到數(shù)據(jù),此時(shí)再打印
console.log(this.data.judgedetaillist[0].fileList.length);
發(fā)現(xiàn)明明數(shù)組中有對象,但是這個(gè)對象根本取不到,并且連length都無法讀取
原因剖析
由于wx.uploadFile默認(rèn)是使用異步,因此在不斷的for循環(huán)中,它返回的值并不是同步的,導(dǎo)致多個(gè)同時(shí)執(zhí)行,此時(shí)數(shù)組使用的是地址引用,并沒有實(shí)際賦值成功,賦值的數(shù)組已經(jīng)被修改了,因?yàn)樵瓉淼拈L度是0,所以獲取不到數(shù)組,但又包含修改后的結(jié)果。
要解決這個(gè)bug就是讓wx.uploadFile可以同步執(zhí)行,需要用到
1、new Promise
2、async,await
3、取消forEach, forEach 中使用 async/await 時(shí),異步操作并不會等待前一個(gè)操作結(jié)束再執(zhí)行下一個(gè),而是會同時(shí)執(zhí)行多個(gè)異步操作
解決方案(非生產(chǎn)環(huán)境代碼)
本來h5中的多圖片上傳是直接使用 async:false就可以,但是在微信中這是無效的。所以代碼寫成這樣
解決方案一
使用new Promise,配合async,await進(jìn)行多次循環(huán)
//圖片上傳函數(shù)
Upload: function (uploadFile) {
return new Promise((resolve, reject) => {
wx.uploadFile({ //這里一定要用 wx.uploadFile 否則無法穿到后臺
filePath: uploadFile, //你要上傳的路徑
name: 'file', //你上傳到后臺的name值
formData: { // 如果你要驗(yàn)證你的token 可以用formData來給后臺傳值
path: "judge"
},
url: 上傳路徑,
success: (res) => {
// 上傳完成操作
const data = JSON.parse(res.data)
resolve({
data: data
})
},
fail: (err) => {
//上傳失?。盒薷膒edding為reject
wx.showToast({
title: "網(wǎng)絡(luò)出錯,上傳失敗",
icon: 'none',
duration: 1000
});
reject(err)
}
});
})
},
//接收返回的路徑,關(guān)鍵是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,當(dāng)所有的異步請求成功后才會執(zhí)行,將全部異步執(zhí)行完后的數(shù)據(jù)一次性返回
調(diào)用測試
console.log(this.uploadImage(this.data.fileList[_k]))
返回結(jié)果
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)
利用這個(gè)可以一次性獲取全部的結(jié)果文章來源:http://www.zghlxwxcb.cn/news/detail-639258.html
代碼示例:文章來源地址http://www.zghlxwxcb.cn/news/detail-639258.html
uploadImage: function(tempFilePaths){
return new Promise((presolve,preject)=>{
if({}.toString.call(tempFilePaths)!='[object Array]'){
throw new TypeError(`上傳圖片參數(shù) tempFilePaths 類型錯誤!`)
}
//路徑數(shù)組為空時(shí) 不上傳
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: { // 如果你要驗(yàn)證你的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'
})
})
})
},
到了這里,關(guān)于微信小程序多圖片上傳實(shí)用代碼記錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!