【微信小程序】选择图片并上传时出现两个loading ?!

遇到这样一个业务场景,在小程序中 wx.chooseImage 选择图片后,

调用 wx.uploadFile 上传图片到公司的一个数据库中,然后拿到对应的返回值后,

再去请求一个接口,将所有图片一一进行绑定,

等所有图片上传完毕后,最后请求一个接口进行总结汇报。

我们希望的是当选择图片完成后,有一个loading加载中的效果,

然后等所有图片上传完毕并一一绑定,且最后一个总结汇报的接口也请求完毕后,

再隐藏loading弹窗,展示“上传完毕”。

听起来很简单的一个事情,但是我却踩坑了。

先看下大体的代码结构…

// 当前索引值
let i = 0;
// 需要上传的图片总数
let picNum = 0;
// 需要上传的图片路径
let picFilePaths;

// 选择图片
choosePic: function () {
     
	const self = this;
   	wx.chooseImage({
     
      	count: 9,
      	sizeType: ['original', 'compressed'],
      	sourceType: ['album', 'camera'],
      	success: (res) => {
     
          	// 小程序API的限制 文件不能大于20M
          	if (res.size > 20971520) {
     
            	wx.showModal({
     
             	 	title: '上传失败',
              		content: '您选择的图片过大,请重新选择',
              		showCancel: false,
              		confirmText: '我知道了',
             		success: (res) => {
     
                		if (res.confirm) {
     
                			// 自定义的向外抛reload事件
                  			self.triggerEvent('reload');
                		}
             		}
            	});
            	return;
          	}
          	this.uploadPic(res.tempFilePaths);
        }
  	});
},
// 上传图片
uploadPic: function (tempFilePath) {
     
  	const self = this;
  	wx.showLoading({
     
     	title: '加载中...',
  	})

  	// 如果是数组说明正在上传多张图片
   	if (Array.isArray(tempFilePath)) {
     
     	// 上传的图片数量
        picNum = tempFilePath.length;
        // 上传的所有图片
        picFilePaths = tempFilePath;
        // 正在上传的图片
        tempFilePath = picFilePaths[i];
  	}

  	wx.uploadFile({
     
      	url: '...',
        filePath: tempFilePath,
        name: '...',
        formData: {
     
         	...
        },
        success: (res) => {
     
          	// 上传文件大于20M会返回413状态码
          	if (res.statusCode == 413) {
     
            	wx.showModal({
     
              		title: '上传失败',
              		content: '上传的图片文件过大,请重新选择',
              		showCancel: false,
              		confirmText: '我知道了',
              		success: (res) => {
     
                		if (res.confirm) {
     
                  			self.triggerEvent('reload');
                		}
              		}
            	});
            	return;
          	}
          	const resData = JSON.parse(res.data);
          	// 取resData中的值
          	...

          	wx.request({
     
            	url: '...',
	            method: 'POST',
	            data: {
     
		         	...
	            },
	           	...
          	})
        },
        fail: (err) => {
     
        	wx.hideLoading();
          	wx.showToast({
     
            	title: err,
           		icon: 'none'
          	});
        },
        complete: () => {
     
         	if (picNum) {
     
            	i++;
            	if (i < picNum) {
     
              		self.uploadPic(picFilePaths);
            	} else {
     
              		...
              		// 请求成功后重新加载数据
                	self.triggerEvent('reload');
                	// 清空正在上传的图片张数
                	i = 0;
                	// 清空需要上传的图片总数
                	picNum = 0;
          		})
         	}
      	} 
   	});
}

刚开始以为 wx.uploadFile 会自动给加个loading的弹窗,所以把这个请求直接屏蔽掉,发现还是有loading弹窗。

然后再看了下自己写的组件里 self.triggerEvent('reload'); 发现都不沾边,只有失败或者最后一个请求成功后才会触发。

接着排查到wx.request,因为看到我公司的一个封装的wx.request方法中只有 wx.hideLoading 而没有 wx.showLoading

好叭,这个挺误导人的,让我以为 wx.request 会自带 wx.showLoading 所以这个封装里才只有 wx.hideLoading

但是后来越想越不对劲,明明官方文档里的 wx.request 请求前后的loading弹窗显示隐藏是需要我们自己去加的。

ok ~ 思路就聚焦到了 wx.chooseImage 这里是不是有问题,莫非选择图片完了会自动重新加载??

然后尝试着多加几个 wx.hideLoading,我当时的脑回路也真是奇葩,最后的结果是没有效果,还是会选择图片完就有个loading。

直到最后我看到网上有個人说 wx.chooseImage 后会触发 app.onShow 方法 (此刻空气突然静止… )

然后我迅速找到这个页面的 onShow 方法,发现有个reload重新加载数据的逻辑,而加载数据时有个 wx.showLoading

所以这就造成了我选择图片并上传后出现两次loading弹窗提示…

第一个短暂的loading弹窗提示是onShow中reload重新加载数据时的showLoading。

而第二个loading弹窗才是我上传图片时加的showLoading。

你可能感兴趣的:(微信小程序)