uni-app 开启uni.showLoading后执行获取token和文件上传功能时,慢速网络切换网络导致一直转圈,无法正常执行请求成功或失败
uni-app 开启uni.showLoading后执行获取token和文件上传功能时,慢速网络切换网络导致一直转圈,无法正常执行请求成功或失败
开发环境 | 版本号 | 项目创建方式 |
---|---|---|
Windows | win10 | CLI |
产品分类:uniapp/App
PC开发环境操作系统:Windows
手机系统:全部
页面类型:vue
vue版本:vue2
打包方式:云端
CLI版本号:2.0.2-3090820231124001
测试过的手机:
- 荣耀Play5
- 小米8
- 华为P30 Pro
- OPPO R17
- 华为畅享10 plus
- 华为P30
示例代码:
//开启转圈
uni.showLoading({
title: "上传中...",
mask: true,
});
//获取token及上传文件方法
// 获取文件管理签名token
UCloudUFile.prototype.getUFileToken = function (options, success, error) {
var method = options.method || "GET";
var file = options.file || {};
var fileName = options.fileName;
var md5Required = options.md5Required;
var keyName;
var contentType = options.contentType || file.type || "";
var putPolicy = options.putPolicy || "";
keyName = fileName;
var that = this;
var token = "";
// 服务端签名计算
function getSignatureToken(
tokenServerUrl,
method,
bucket,
key,
content_md5,
content_type,
date,
put_policy
) {
var url =
tokenServerUrl +
"?method=" +
method +
"&bucket=" +
bucket +
"&key=" +
key +
"&content_md5=" +
content_md5 +
"&content_type=" +
content_type +
"&date=" +
date +
"&put_policy=" +
Base64.encode(put_policy);
var reqData = appendExtraParam(tokenServerUrl, {});
uni.request({
url: url,
method: "POST",
header: requestFormHeader(),
data: reqData,
success: (resp) => {
success(resp.data.trim());
},
fail: (resp) => {
error("UFile token 获取失败");
},
complete: (resp) => {
//
},
});
}
this.getUFileToken(
requestToken,
function (token) {
var url = that.getBucketUrl() + encodeURIComponent(fileName);
uni.uploadFile({
url: url,
header: {
"Content-MD5": "",
},
filePath: file,
name: "file",
formData: {
FileName: fileName,
Authorization: token,
},
success: (resp) => {
if (resp.statusCode === 200) {
success({
fileName: fileName,
});
}
// success(resp)
console.log("成功上传", resp);
},
fail: (resp) => {
error({
fileName: fileName,
});
console.log("上传失败", resp);
},
});
},
function (error) {}
);
};
//调用token及上传方法后关闭loading
this.ufile.batchUpload(
waitFilesUFile,
async (resp) => {
uni.hideLoading();
console.log("batchUpload resp", resp);
// 这里校验上传之前的图片数量和上传之后图片数量是否一致 TODO
let successFiles = [];
let fileNames = "";
// 假设一致
for (let i = 0; i < resp.length; i++) {
fileNames += resp[i].fileName + ",";
successFiles.push({
fileName: resp[i].fileName,
fullPath: "",
thumbFullPath: "",
shouldReUpload: false,
});
}
//
const responseBody = await fetchMakePrivateUrl({
fileNames: fileNames,
});
if (!responseBody) {
return;
}
console.log("responseBody", responseBody);
for (let i = 0; i < successFiles.length; i++) {
successFiles[i] = responseBody.data[i];
}
console.log("successFiles", successFiles);
this.handleUploadResult(200, successFiles, fromType, fromIndex);
},
(resp) => {
uni.hideLoading();
uni.showModal({
title: "",
content: "图片上传失败:" + JSON.stringify(resp),
});
console.log("上传失败", resp);
},
(progress) => {
console.log("progress", progress);
if (progress === 1) {
uni.hideLoading();
} else {
this.progressCent = "上传中...";
}
}
);
监听下上传进度, 看是否还在上传只是上传比较慢, 如果还是正在上传的过程中, 那肯定不会执行关闭loading
用哪个方法可以监听到上传进度
回复 7***@qq.com: onProgressUpdate
回复 y***@jiayuxiangmei.com: 文档上有 文档
在 uni-app
中,使用 uni.showLoading
显示加载动画时,如果在慢速网络环境下切换网络,可能会导致请求一直处于挂起状态,无法正常执行成功或失败的回调,从而导致页面一直转圈。这种情况通常是由于网络切换时,请求被中断或超时,但 uni.showLoading
没有被正确关闭。
解决方案
-
设置请求超时时间: 在发起网络请求时,可以通过
timeout
参数设置请求的超时时间,防止请求长时间挂起。例如:uni.request({ url: 'https://example.com/api', method: 'GET', timeout: 10000, // 设置超时时间为10秒 success: (res) => { console.log(res.data); }, fail: (err) => { console.error('请求失败', err); }, complete: () => { uni.hideLoading(); // 无论请求成功或失败,都关闭加载动画 } });
-
监听网络状态变化: 可以通过
uni.onNetworkStatusChange
监听网络状态的变化,在网络切换或断开时,手动关闭uni.showLoading
并提示用户网络状态异常。uni.onNetworkStatusChange((res) => { if (!res.isConnected) { uni.hideLoading(); // 关闭加载动画 uni.showToast({ title: '网络已断开,请检查网络连接', icon: 'none' }); } });
-
使用
Promise
和async/await
控制流程: 可以通过Promise
和async/await
来控制网络请求的流程,确保在请求完成或超时后关闭uni.showLoading
。function fetchToken() { return new Promise((resolve, reject) => { uni.request({ url: 'https://example.com/api/token', method: 'GET', timeout: 10000, success: (res) => { resolve(res.data); }, fail: (err) => { reject(err); } }); }); } async function getTokenAndUploadFile() { uni.showLoading({ title: '加载中...', mask: true }); try { const token = await fetchToken(); // 继续执行文件上传等操作 console.log('Token获取成功', token); } catch (error) { console.error('请求失败', error); uni.showToast({ title: '请求失败,请稍后重试', icon: 'none' }); } finally { uni.hideLoading(); // 无论成功或失败,都关闭加载动画 } } getTokenAndUploadFile();
-
使用
uni.hideLoading
的时机: 确保在请求的complete
回调中调用uni.hideLoading
,这样可以保证无论请求成功或失败,加载动画都会被关闭。uni.request({ url: 'https://example.com/api', method: 'GET', success: (res) => { console.log(res.data); }, fail: (err) => { console.error('请求失败', err); }, complete: () => { uni.hideLoading(); // 关闭加载动画 } });