微信小程序基础api封装三部曲(三)

本文探讨了微信小程序从2.10.2基础库版本开始,如何进行网络请求的封装,特别是对于异步API的支持,既可以选择callback,也可以使用Promise。重点讲述了downloadFile、request、uploadFile等有返回值的接口如何进行Promise封装,提供了自定义封装的方法。
摘要由CSDN通过智能技术生成
3.微信小程序 网络请求封装 (小程序基础库 从 2.10.2 开始 ,异步API 支持callback & Promise 两种调用方式)

 

当接口参数 Object对象中不包含success/fail/complete时,将默认返回promise,否则仍然按回调方式执行,无返回值。

但部分接口如,downloadFile, request, uploadFile等本身就有返回值,因此不支持promise调用方式,它们需要 promisify需要开发者自行封装 ,可参考Axios 封装 

方式一:自定义封装  

//-- 1、 请求文件 request.js
/***
* 封装类似 axios 调用请求方法
* 功能:
*  1.可实例化默认配置,带请求拦截和响应拦截, 可配置基础路径(可抽离切换不同环境域名)+ 接口路径
*  2. 带默认loading效果(可配置不展示)
*  3.带简单请求api:get/post/put/delete
*  4.可拦截token ,token不存在或失效可跳转登录页面
*  5. 支持上传方法
*
*/


class WxRequest {

  // 默认请求参数

  defaults = {
    baseUrl: "", // 请求基准地址
    url: "", // 开发者服务器接口地址
    data: null, // 请求参数
    method: "GET", // 默认请求方法
    // 请求头 
    header: {
      "Content-type": "application/json" // 设置数据交互格式
    },
    timeout: 60000, // 小程序默认请求超时 默认1分钟
    isLoading: true // 是否使用默认loading , true使用 false 不使用
  }

  // 定义拦截器对象  包含请求拦截 和响应拦截
  interceptors = {
    // 请求拦截 在发出请求前 对参数进行新增和修改 
    request: (config) => config,

    // 响应拦截 在服务器响应数据后 进行逻辑处理
    response: (response) => response
  }

  // 定义数组队列,用来存储请求队列、存储请求标识
  queue = []

  // 用于创建和初始化类的属性和方法
  // 在实例化时 传递的参数会被 constructor 形参接收
  constructor(params = {}) {
    // 通过 Object.assign() 方法合并参数
    // 需要传入的参数覆盖默认参数,因此传入的参数放到最后
    this.defaults = Object.assign({}, this.defaults, params)
  }

  // 发起请求 属性值和wx.request 保持一致 
  // 实例方法接收一个对象类型参数
  request(options) {

    //如果有新的请求,就清除上一次的定时器
    this.timerId && clearTimeout(this.timerId)

    //注意:需要先合并完整的请求地址(baseUrl + url)
    options.url = this.defaults.baseUrl + options.url

    // 合并调用时请求的参数 
    options = {
      ...this.defaults,
      ...options
    }
    //  在发送之前  调用请求拦截器 
    options = this.interceptors.request(options)

    if (options.isLoading && options.method !== "UPLOAD") {
      // 判断queue队列是否为空,若是空就展示loading; 若是不为空就不调用 wx.showLoading 
      this.queue.length === 0 && wx.showLoading()

      // 往队列里添加 自定义请求标识
      this.queue.push("request")
    }

    // 返回一个promise
    return new Promise((reslove, reject) => {
      // 是否时上传方法
      if(options.method === "UPLOAD"){
        wx.uploadFile({
          ...options,
          success:(res)=>{
            // 需要将后台返回json字符串 通过JSON.parse 转换
            res.data = JSON.parse(res.data)
            // 合并参数 
            const mergeRes = Object.assign({}, res, { config:options, isSuccess: true })
            reslove(this.interceptors.response(mergeRes))
          },
          fail: (err)=>{
            // 合并参数 
            const mergeErr = Object.assign({}, err, { config:options, isSuccess: false })
            reject(this.interceptors.response(mergeErr))
          }
        })
      }else{
        wx.request({
          ...options,
          success: (res) => {
            // 不管成功还是失败 都需要调用响应拦截
            // 在给响应拦截器传参时,需要把请求参数一起传递过去,方便调试排查 
            // 传递参数前,进行参数合并
  
            // 不管时请求成功还是失败,都将数据传递给了拦截器
            // 追加1个属性 isSuccess  ,值为true  执行success ,值为false 执行fail
  
  
            const mergeRes = Object.assign({}, res, {
              config: options,
              isSuccess: true
            })
            reslove(this.interceptors.response(mergeRes))
          },
          fail: (err) => {
            // 不管成功还是失败 都需要调用响应拦截
            const mergeErr = Object.assign({}, err, {
              config: options,
              isSuccess: false
            })
            reject(this.interceptors.response(mergeErr))
  
          },
          // 不管成功或失败都会执行
          complete: () => {
  
            if (options.isLoading) {
              // 在每次请求后都会走complete 回调函数
              // 每次 从 queue队列清除一个请求标志
              this.queue.pop()
  
              // 解决两个请求有依赖关系时,loading闪烁问题(解决方法:利用延迟回调)
  
              this.queue.length === 0 && this.queue.push("request")
  
              this.timerId = setTimeout(() => {
                this.queue.pop()
  
                // 删除标志后 判断队列是否为 空 ,若为空 说明并发多次请求都完成了,就需要隐藏loading 
                this.queue.length === 0 && wx.hideLoading()
              }, 1)
            }
  
          }
  
        })
      }
      
    })
  }

  //-----------封装快捷操作方法
  // 封装 GET 实例方法 
  get(url, data = {}, config = {}) {
    // 返回 基于 request 方法 封装的参数合并 请求
    return this.request(Object.assign({
      url,
      data,
      method: "GET"
    }, config))
  }
  // 封装 DELETE 实例方法 
  delete(url, data = {}, config = {}) {
    // 返回 基于 request 方法 封装的参数合并 请求
    return this.request(Object.assign({
      url,
      data,
      method: "DELETE"
    }, config))
  }
  // 封装 POST 实例方法 
  post(url, data = {}, config = {}) {
    // 返回 基于 request 方法 封装的参数合并 请求
    return this.request(Object.assign({
      url,
      data,
      method: "POST"
    }, config))
  }
  // 封装 PUT 实例方法 
  put(url, data = {}, config = {}) {
    // 返回 基于 request 方法 封装的参数合并 请求
    return this.request(Object.assign({
      url,
      data,
      method: "PUT"
    }, config))
  }

  // 处理并发请求 
  all(...promise) {
    // 通过展开运算符得到传入参数数组 
    return Promise.all(promise)
  }

  /**
   * 上传方法
   * @param {*} url 开发者服务器地址
   * @param {*} filePath 要上传文件资源的路径 (本地路径)
   * @param {*} name 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容
   * @param {*} config 其他配置
   */
  upload(url, filePath, name="file", config = {}){
    return this.request(Object.assign({url,filePath, name, method:"UPLOAD" },config))
  }
}
export default WxRequest

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值