问题:小程序上传文件后我需要后端返回的一个值,但这个值总是在最后面导致需要这个值的方法总是报错,打印测试后发现这它是异步的。但直接使用 await来等待也不行。
uploadImg.wxml
<view class="upload-wrap">
<view class="list-wrap">
<view class="item" wx:for="{{fileList}}" wx:key="index" wx:for-index="index" wx:for-item="item">
<image class="file" src="{{item.url}}" data-url="{{item.url}}" bindtap="viewImage"></image>
<view wx:if="{{!disabled}}" class="icon-delete" data-index="{{index}}" bindtap="delFile">
<image class="icon-delete" src="/images/common/icon-delete.png" mode="widthFix"></image>
</view>
</view>
<view wx:if="{{!disabled && fileList.length<maxCount}}" class="add-wrap" bindtap="chooseFile">
<image class="icon-camera" src="/images/common/icon-camera.png" mode="widthFix"></image>
</view>
</view>
</view>
uploadImg.js
const app = getApp();
Component({
properties: {
pageFileList: {
optionalTypes: [Array, String],
value: () => {
return []
},
observer: function (newValue, oldValue) {
let list;
if (!newValue) {
list = [];
} else if (typeof newValue == 'string') {
list = JSON.parse(newValue);
}
this.setData({
fileList: list
})
}
},
disabled: {
type: Boolean,
default: false
},
maxSize: {
type: Number,
value: 5242880, // 5M
},
maxCount: {
type: Number,
value: 9,
},
category: {
type: String,
value: 'Personal', // 1:Personal,2:Article,3:Meeting
},
name: {
type: String,
value: 'Image'
},
// 文件类型
fileType: {
type: Number,
value: 1, // 1:Image,2:Video,3:Excel,4:PDF文件
},
},
data: {
fileList: [],
},
methods: {
// 选择图片
chooseFile() {
let choseImgCount;
let fileListLen = this.data.fileList.length;
let maxCount = this.data.maxCount;
// 计算每次可上传的文件数量
if (fileListLen == maxCount) {
choseImgCount = 0;
} else if (maxCount - fileListLen > 9) {
choseImgCount = 9;
} else {
choseImgCount = maxCount - fileListLen;
}
wx.chooseImage({
count: choseImgCount,
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 选择图片的来源
success: (res) => {
// 限制最大文件体积
let overSizeIndex = res.tempFiles.findIndex(v => v.size > this.data.maxSize);
if (overSizeIndex > -1) {
let msg = "";
if (res.tempFiles.length > 1) {
msg = "第" + (overSizeIndex + 1) + "个文件已经超过了最大文件限制:"
} else {
msg = "该文件已经超过了最大文件限制:"
}
app.alert.show(msg + (this.data.maxSize / 1024 / 1024).toFixed(0) + "M,请重新上传~");
return;
}
this.uploadFile(res.tempFilePaths);
}
});
},
// 上传图片
async uploadFile(tempFilePaths) {
wx.showLoading({
title: '上传中...',
mask: true
})
for (let i = 0; i < tempFilePaths.length; i++) {
await this.uploadFileHandler(tempFilePaths, i);
if (i == tempFilePaths.length - 1) {
this.triggerEvent("uploadFiles", { list: this.data.fileList, name: this.data.name });
wx.showToast({
title: '上传成功',
icon: 'none',
duration,
})
}
}
},
uploadFileHandler(tempFilePaths, i) {
let self = this;
let fileList = self.data.fileList;
return new Promise((resolve, reject) => {
wx.uploadFile({
url: app.siteinfo.apiUrl + '', // 需要用HTTPS,同时在微信公众平台后台添加服务器地址
filePath: tempFilePaths[i], // 上传的文件本地地址
name: 'file', // 服务器定义的Key值
header: {
'content-type': 'multipart/form-data',
'cookie': wx.getStorageSync('cookie')
},
formData: {
uploadDir: self.data.category,
fileType: self.data.fileType,
},
success: function (res) {
wx.hideLoading()
if (res.statusCode == 200) {
let result = JSON.parse(res.data);
if (result.status) {
let list = [{ name: self.data.name, url: result.data.fileurl }];
fileList = fileList.concat(list);
self.setData({ fileList });
resolve();
} else {
app.alert.show(result.errmsg, reject(result.errmsg));
}
} else {
app.alert.show('状态:' + res.statusCode + ',提示:' + res.errMsg, reject(res.errMsg));
}
},
fail: function (err) {
wx.hideLoading()
app.alert.show(err.errMsg, reject(err.errMsg));
}
});
})
},
// 删除图片
delFile(e) {
wx.showModal({
title: '提示',
content: '确定要删除吗?',
success: res => {
if (res.confirm) {
let fileList = this.data.fileList;
fileList.splice(parseInt(e.currentTarget.dataset.index), 1);
this.setData({ fileList })
this.triggerEvent("uploadFiles", {
list: fileList,
name: this.data.name
});
wx.showToast({
title: '删除成功',
icon: 'success',
duration: 2000
})
}
}
})
},
// 预览图片
viewImage(e) {
let urls = this.data.fileList.map(item => { return item.url });
wx.previewImage({
current: e.currentTarget.dataset.url,
urls
});
},
}
})
uploadImg.less
.upload-wrap {
.list-wrap {
display: flex;
flex-wrap: wrap;
.item {
position: relative;
width: 188rpx;
height: 188rpx;
margin-top: 40rpx;
margin-right: calc(~"(100% - 564rpx) / 3");
.file {
width: 100%;
height: 100%;
vertical-align: middle;
border-radius: 8rpx;
}
.icon-delete {
width: 40rpx;
position: absolute;
right: -10rpx;
top: -10rpx;
}
}
}
.add-wrap {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 188rpx;
height: 188rpx;
margin-top: 40rpx;
border: 1px dashed #979797;
border-radius: 8rpx;
background-color: #f9fafb;
text-align: center;
.icon-camera {
width: 50rpx;
height: 46rpx;
pointer-events: none;
}
}
}
uploadImg.json
{
"component": true,
"usingComponents": {}
}
应用
<upload-img category="Personal" pageFileList="{{form.image}}" maxCount="3" disabled bind:uploadFiles="uploadFiles">
</upload-img>
data: {
form: {
image: '[{"name":"Image","url":"https://wechatmp.uatwechat.com/upload/PersonalCompressed/20230614/20230614114423503.jpeg"}]',
video: ''
},
},
uploadFiles(e) {
let str = "form." + e.detail.name;
let list = e.detail.list;
if (list.length > 0) {
this.setData({
[str]: JSON.stringify(e.detail.list)
})
} else {
this.setData({
[str]: '',
})
}
},
app.alert方法封装 alert.js,然后在在app.js引入可使用
const show = (message, showCancel, successCallback = function() {}) => {
wx.showModal({
title: '提示',
content: message,
confirmColor: '#DB6276',
showCancel: showCancel,
success(res) {
if (res.confirm) {
successCallback();
}
}
})
}
module.exports = {
show
}
小程序上传多张图片