初识小程序-uploadFile封装

132 阅读4分钟

默认使用方式

page({
  ...
  // 获取微信头像
  chooseavatar(event){
   const {avatarUrl}=event.detail;
   // 目前获取的微信头像是临时路径
   // 临时路径是有失效时间的,需要将临时路径上传到公司服务器
   this.setData({avatarUrl})
   this.wxUploadFile(avatarUrl);
  },
  wxUploadFile(avatarUrl){
    wx.uploadFile({
      // 要上传的文件路径
      filePath: avatarUrl, 
      // 文件对应的key,服务器需要根据key来获取文件的二进制信息
      name: 'file',
      // 接口地址
      url: 'https://gmall-prod.atguigu.cn/mall-api/fileUpload', 
      success: (result) => {
        console.log("result",JSON.stringify(result))
      },
      fail: (res) => {},
      complete: (res) => {},
    })
  }
  ...
})
<button open-type="chooseAvatar" bindchooseavatar="chooseavatar">
<image src="{{avatarUrl}}" mode=""/>
获取微信头像
</button>

封装uploadFile

class WxRequest {
  ......
  request(options){
    ......
    return new Promise((resolve,reject)=>{
      ......
      if(options.method === "UPLOAD"){
        wx.uploadFile({
          ...options,
          success:(res)=>{
            // 需要将服务器返回的字符串转换为对象
            res.data=JSON.parse(res.data);
            const mergeRes = Object.assign({},res,{config:options,isSuccess:true})
            resolve(this.interceptors.response(mergeRes))
          },
          fail:()=>{
            const mergeErr = Object.assign({},err,{config:options,isSuccess:false})
            reject(this.interceptors.response(mergeErr))
            }
        })
        return
      }
      ......
  })
  uploadFile(url,filePath,name="file",config={}){
    return this.request(Object.assign({url,filePath,name,method:"UPLOAD"},config))
  }
}
  // 获取微信头像
  chooseavatar(event){
   const {avatarUrl}=event.detail;
   instance.uploadFile("https://gmall-prod.atguigu.cn/mall-api/fileUpload",avatarUrl).then(res=>{
     // 使用服务器返回的路径
    this.setData({avatarUrl:res.data})
   })
  },

完整代码

// 通过类封装,提高代码复用性,也可方便添加新的属性和方法
class WxRequest {
  // 默认参数对象
  defaults={
   baseURL:"", // 基准地址
   url:"", // 接口地址
   data:null, // 请求参数
   method:"GET",
   header:{
     "Content-type":"application/json", // 设置数据交互格式
   },
   isLoading:true, // 控制是否使用默认的loading,true表示使用默认的loading
   timeout:60000 // 默认超时时间一分钟
  }

  // 定义拦截器对象
  // 需要包含请求拦截器以及响应拦截器,方便请求以及响应时进行逻辑处理
  interceptors={
    // 请求拦截器
    // 请求发送之前,对请求参数进行新增、修改,默认不处理
    request(config){
     return config
    },

    // 响应拦截器
    // 服务器响应数据以后,对数据处理,默认不处理
    response(response){
    return response
    }

  }
  // 初识空数组,用来存储请求队列
  queue = []
  // 默认参数合并在constructor进行,将传入的参数与defaults合并,覆盖默认配置
  constructor (params={}) {
    this.defaults=Object.assign({},this.defaults,params);
  }
  request(options){
    // 如果有新的请求,就
    this.timer && clearTimeout(this.timer)
    // 合并完整的请求地址
    options.url=this.defaults.baseURL+options.url;

    // 合并请求参数
    options = {...this.defaults,...options}
    // 在请求之前调用请求拦截器,用于新怎或修改参数 uploadFile有自己的loading,不用开启
    options=this.interceptors.request(options)
    if(options.isLoading && options.method !== "UPLOAD"){
      // 判断请求队列queue是否为空,如果是空,就显示loading
      this.queue.length===0 && wx.showLoading();

      // 向queue中添加请求标识
      // 每个标识代表是一个请求,标识是自定义的
      this.queue.push("request");
    }
    return new Promise((resolve,reject)=>{
      if(options.method === "UPLOAD"){
        wx.uploadFile({
          ...options,
          success:(res)=>{
            // 需要将服务器返回的字符串转换为对象
            res.data=JSON.parse(res.data);
            const mergeRes = Object.assign({},res,{config:options,isSuccess:true})
            resolve(this.interceptors.response(mergeRes))
          },
          fail:()=>{
            const mergeErr = Object.assign({},err,{config:options,isSuccess:false})
            reject(this.interceptors.response(mergeErr))
            }
        })
        return
      }
      // 使用wxwx.request发送请求时,
      // 只要成功接收到服务器返回结果
      // 无论状态码是多少,都会执行 success
      // 需要根据状态码,自己做判断
      wx.request({
        ...options,
        success(res){
          // 不管响应成功还是失败,都需要调用响应拦截器
          // 响应拦截器需要接收服务器响应数据,对数据进行逻辑处理,处理好后返回
          // 然后通过resolve将数据返回

          // 给响应拦截器传递参数时,需要将请求参数也一起传递
          // 方便调试及其他逻辑处理,需要先合并
          // 然后将合并的参数传给拦截器

          // 新增isSuccess字段用于区分响应成功还是失败
          const mergeRes = Object.assign({},res,{config:options,isSuccess:true})
          resolve(this.interceptors.response(mergeRes))
        },
        // 一般网络异常时(如请求超时),会走fail
        fail(err){
          const mergeErr = Object.assign({},err,{config:options,isSuccess:false})
          reject(this.interceptors.response(mergeErr))
        },
        complete(){
          if(options.isLoading && options.method !== "UPLOAD"){
            // 不管成功还是失败,隐藏loading
            wx.hideLoading();
            // 每次结束后删除该标识
            this.queue.pop();
            this.queue.length === 0 && this.queue.push("request")
            this.timer=setTimeout(()=>{
              // 每次结束后删除该标识
              this.queue.pop();
              // 删除标识以后,需要判断queue是否为空
              // 如果请求为空,则并发请求完成,则隐藏loading
              this.queue.length === 0 && wx.hideLoading()
              clearTimeout(this.timer)
            })
          }
        }
      })
    })
  }
  get(url,data={},config={}){
    return this.request(Object.assign({url,data,method:"GET"},config))
  }
  post(url,data={},config={}){
    return this.request(Object.assign({url,data,method:"POST"},config))
  }
  put(url,data={},config={}){
    return this.request(Object.assign({url,data,method:"PUT"},config))
  }
  delete(url,data={},config={}){
    return this.request(Object.assign({url,data,method:"DELETE"},config))
  }
  uploadFile(url,filePath,name="file",config={}){
    return this.request(Object.assign({url,filePath,name,method:"UPLOAD"},config))
  }
}
const instance = new WxRequest()
// 配置请求拦截器
instance.interceptors.request= config =>{
  // 请求发送前,添加loading效果
  wx.showLoading();

  const token="";
  if(token){
    config.header.token=token
  }
  return config
}

// 配置响应拦截器
instance.interceptors.response = response => {
  let {isSuccess,data} = response
  if(!isSuccess){
    wx.showToast({
      title: '网络异常',
      icon:"error"
    })
    return response
  }
  switch (data.code) {
    // 如果后端返回的业务状态码等于 200 说明数据响应成功
    case 200:
      return data;
    case 208: // token失效,跳回登录页
      // 清除失效token,清除本地全部信息
      // wx.clearStorage()
      // wx.navigateTo({
      //   url: 'url',
      // })    
      return Promise.reject(response);
      default :
      // 抛出异常
      break;
      

  }
  return response
}

export default instance