技術概述
微信小程序要上傳多圖,並讓多個上傳進程最後保持同步返回結果,也適用於各種文件的上傳
技術詳述
上傳一張圖片
上傳一張圖片到微信存儲需要先獲取文件的後綴名,才能在雲端讀取時不出錯
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)微信小程序之上傳多張圖片(雲開發)