让Promise更加优雅(商品图片视频评论)-微信小程序

291 阅读3分钟

微信是不支持同时上传多张图片的,那要怎么优雅处理一次上传多张图片呢?

直接用场景入场吧:

商品订单的评论,一次可以对多个商品进行评论,每个商品又可以上传图片+视频,那怎么把这些需求放到一起统一处理?

  • 商品

    • 内容
    • 图片 (需要先上传获取服务器临时地址,可以上传多张)
    • 视频 (需要先上传获取服务器临时地址,只能最多一个视频)
  • 商品

    • 内容
    • 图片
    • 视频
  • 商品

    • 内容
    • 图片
    • 视频
  • 提交数据

那就看一出好戏吧:

// 提交评论数据
submitAction(){

    // 创建请求队列数组
    var promiseAll = [];
    // 判断是否对该订单评论了,有添加入队列中
    for (let index = 0; index < this.data.commentModels.length; index++) {
       // 组装请求队列
      let request = this.requestUploadData(index)
      promiseAll.push(request)
    }
    Promise.all(promiseAll).then((res)=>{
      //所有请求完成了
      console.log('完毕!!!')
      setTimeout(() => {
        wx.navigateBack()
      }, 1500);
      wx.showToast({
        title: '评论已提交',
      })
      
    })
  },

// 这是单个商品的评论内容+图片+视频
  requestUploadData(index) {

    let sectionVideos = this.data.sectionVideos
    let sectionUploadImages = this.data.sectionUploadImages

    const comment = this.data.commentModels[index];
    var promiseAll = [];
    if (sectionVideos[index]) { // 有视频
    // 上传视频,获取成功之后的临时服务器视频地址,用于评论提交接口的视频参数
      let request = requestPromise({
        url: API.uploadFile,
        filePaths: [sectionVideos[index]],
        fileNames: ['multipartFile'],
        data: {
          type: 6
        }
      })
      promiseAll.push(request)
    }
    // 有图片
    let uploadImages = sectionUploadImages[index]
    if (uploadImages && uploadImages.length > 0) {
      let names = uploadImages.map((v)=>{return 'multipartFile'});
      // 图片类似于视频的操作方式
      let request = requestPromise({
        url: API.uploadFile,
        filePaths: uploadImages,
        fileNames: names,
        data: {
          type: 3
        }
      })
      promiseAll.push(request)
    }

    // 将数据组装成一个promise
    return Promise.all(promiseAll).then(res => {
      var data = {
        ...comment
      }
      res.forEach((v, i) => {
        if (sectionVideos.length > 0 && i == 0) {
          // 有视频路径
          data['video'] = v[0]
        } else {
          // 图片路径
          if (sectionVideos.length > 0) {
            // 有视频的封面
            data['videoImage'] = v.shift()['imagePath']
          }
          data['picturesList'] = v.map((value)=>value.imagePath)
          
        }
      })
     
      // 提交单挑数据
      return requestPromise({
        url: API.orderComment,
        method: 'POST',
        data: data,
        header:{'Content-Type':'application/json'},
      })
    })
  },

这里第一次看,你会看到很多嵌套关系,而且看得有些云里雾里的。所以我做一个简单的说明

requestPromise: 这是封装好的数据请求类,包括图片上传,多张图片上传,其实调的是 wx.uploadFile

所有的请求都组装到 Promise 再做统一一次性的请求。

如果你理解了 Promise 使用方法,加上 Promise.all。 便不难理解上面的写法。

requestPromise 的封装代码如下

let ajaxTimes = 0;
/** 使用方式:
 * requestPromise({
        url:'url', // 必须的
        data:data,
        filePaths:[],
        fileNames:[],
        header:[:],
        method:'GET',
        hiddenLoading:false,
        success:(orgRes)=>{
          // 这里接收的是原始数据
        }
      }).then((result)=>{
        // 这里接收的是data.data的数据
      }).catch((error)=>{
      })
 * 
 */
function requestPromise(params) {

  // 判断 url中是否带有 /my/ 请求的是私有的路径 带上header token
  var header = {
    ...params.header
  };
  var build = buildRequestHeader()
  header = {
    ...build,
    ...header
    
  }

  ajaxTimes++;
  // 显示加载中 效果
  if (!params.hiddenLoading) {
    wx.showLoading({
      title: "加载中",
      mask: true
    });
  }

  // 定义公共的url
  const baseUrl = getApp().globalData.httpHost;

  return new Promise((resolve, reject) => {

    var url = baseUrl + 'shop/' + params.url

    // 上传文件
    if (params.filePaths && params.filePaths.length > 0) {
      // 是上传文件
      var index = 0
      var respDatas = []
      function uploadImage(filePaths) {
        wx.uploadFile({
          filePath: filePaths[index],
          name:  params.fileNames ? params.fileNames[index] : 'file',
          formData: params.data,
          header: header,
          url: url,
          success (res){
            let jsonData = JSON.parse(res.data)
            const data = jsonData.data
            respDatas.push(data)
            index += 1
            if (index == params.filePaths.length) {
              resolve(respDatas);
              //  关闭正在等待的图标
              ajaxTimes--;
              if (ajaxTimes === 0) {
                //  关闭正在等待的图标
                wx.hideLoading();
              }
              return;// 已经上传完了
            }
            uploadImage(filePaths)
          }
        })
      }
      uploadImage(params.filePaths)


      return;
    }
    // 结束上传文件


    wx.request({
      ...params,
      header: header,
      url: url,
      success: (result) => {
        if (result.data.code == 200) {
          resolve(result.data.data);
          if (params && params.success) {
            params.success(result.data);
          }
          // 暂时不知道这里为什么会阻住之后的代码执行,只好先放在最后了
          analysisResponseHeader(result.header)
        } else if (result.data.code == 205) {
          // 未登录需要重新登录
          reject(result.data.msg);

          let pages = getCurrentPages();
          let page = pages.pop().route;
          console.log(page)
          if (page != 'pages/loginphone/index') {
            wx.navigateTo({
              url: '/pages/loginphone/index',
            })
          }
          // 清空用户信息
          wx.setStorageSync('serverIsLogin', false)
          getApp().globalData.wxLoginCode = null

        } else {
          reject(result.data.msg);
          var msg = result.data.msg ?? "";
          if (msg.length > 6) {
            if (msg.length > 100) {
              msg = msg.substring(0, 100) + "...";
            }
            wx.showModal({
              title: msg,
              showCancel:false,
            }) 
          }else {
            wx.showToast({
              title: msg,
            })
          }
        }
      },
      fail: (err) => {
        reject(err.errMsg);
      },
      complete: () => {
        ajaxTimes--;
        if (ajaxTimes === 0) {
          //  关闭正在等待的图标
          wx.hideLoading();
        }
      }
    });
  })
}

// 解析响应头部信息来更新用户 sessionId
function analysisResponseHeader(header) {
  var cookie = header["Cookie"]
  if (!cookie) {
    cookie = header["Set-Cookie"]
  }
  if (cookie && cookie.indexOf("sessionId=") >= 0) {
    cookie = cookie.replace('sessionId=', '')
    var iv = header["iv"]
    var sessionId = signature.decrypt(cookie, iv)
    if (sessionId) {
      wx.setStorageSync('user_sessionId', sessionId)
    }
  }
}

// 组装请求头部信息
function buildRequestHeader() {
  var header = {}
  header["mini-version"] = getApp().globalData.mini_version
  header["Content-Type"] = "application/x-www-form-urlencoded"
  // User-Agent
  var iv = signature.getIVTimestamp()
  var sessionId = wx.getStorageSync('user_sessionId')
  if (sessionId) {
    var cookie = signature.encrypt(sessionId, iv)
    header["Cookie"] = "sessionId=" + cookie
    header["iv"] = iv
  }
  return header
}