技術概述

微信小程序要上傳多圖,並讓多個上傳進程最後保持同步返回結果,也適用於各種文件的上傳

技術詳述

上傳一張圖片

上傳一張圖片到微信存儲需要先獲取文件的後綴名,才能在雲端讀取時不出錯

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是

readHoldingRegisters同步_上傳

技術使用中遇到的問題和解決過程。

遇到的問題:上傳時如果以時間戳作為文件名可能會出現兩個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)微信小程序之上傳多張圖片(雲開發)