小程序请求封装以及拦截器

通常我们使用 axios 库中的 API 设置常用配置以及请求方法封装。更多详情,请查看:axios 常用配置以及请求方法封装。小程序中使用 wx.request  API 进行网络请求数据,但是小程序中未对请求提供拦截 API。在 Taro 框架中,我们可以看的 Taro.addInterceptor(callback) API 可以使用拦截器在请求发出前或发出后做一些额外操作。这里的提供的拦截器:请求拦截和响应拦截是没有区分的。

一、请求封装

wx.request 参数说明:

属性 类型 默认值 必填 说明 最低版本
url string   开发者服务器接口地址  
data string/object/ArrayBuffer   请求的参数  
header Object   设置请求的 header,header 中不能设置 Referer。
content-type 默认为 application/json
 
timeout number   超时时间,单位为毫秒 2.10.0
method string GET HTTP 请求方法  
dataType string json 返回的数据格式  
responseType string text 响应的数据类型 1.7.0
enableHttp2 boolean false 开启 http2 2.10.4
enableQuic boolean false 开启 quic 2.10.4
enableCache boolean false 开启 cache 2.10.4
success function   接口调用成功的回调函数  
fail function   接口调用失败的回调函数  
complete function   接口调用结束的回调函数(调用成功、失败都会执行)

object.method 的合法值:OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT。

通常我们的接口请求主要为 POST 和 GET 请求两种方式。更多详情参数,请查看:Taro 官网之 Taro.request API。

url 为必传参数,data、method、header 为非必传参数。

class HTTP {
  request({
    url,
    data = {},
    method = 'GET',
    header = {'content-type': 'application/json'}
  }) {
    return new Promise((resolve, reject) => {
      this._request(url, resolve, reject, data, method, header)
    }).catch((reject) => {
      console.log('catch', reject)
    })
  }
}
export { HTTP }

之所以要封装一下 wx.request API 的缘由:首先我们请求时,有些接口需要在请求前添加 loading 样式,待到请求结果响应时,将 loading 样式隐藏,同时接口中可能需要添加请求头之类的。

class HTTP {
  // data 默认空, method 默认为 GET
  _request(url, resolve, reject, data = {}, method = 'GET', header = {'content-type': 'application/json'}) {
    let headerParam = { 
      Authorization: wx.getStorageSync("tokenInfo").token
    };
    this._show()
    Taro.request({
      url,
      method,
      data,
      header: {
        ...header,
        ...headerParam,
      },
      success: (res) => {
        wx.hideLoading()
        if (res.statusCode == 200) {
          resolve(res.data)
        } else {
          reject()
        }
      },
      fail: (err) => {
        wx.showToast({
          title: '服务器网络错误!',
          icon: 'loading',
          duration: 1500
        })
        reject()
      }
    })
  }
  _show(){
    wx.showLoading({
      title: '加载中',
    })
  }
}

export { HTTP }

在接口定义文档中,我们只需采用 class 的 extends 继承封装的请求方法。

// src/servers/servers.js
import { HTTP } from '../utils/http.js'

const API = {
  login: "login/decodeUserInfo", // 登录
  ......
}
class MineModel extends HTTP {
  // 登陆
  getLogin(encryptedData, iv, code){
    return this.request({
      url: API.login,
      data: {
        encryptedData,
        iv,
        code,
      },
      method: 'POST',
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
    })
  }
}
export { MineModel }

如何在页面中使用呢?

import {  MineModel } from '../../models/mine.js'

const mineModel = new MineModel()

// 请求第三方接口
mineModel.getLogin(res.encryptedData, res.iv, code).then(res => {
  console.log('请求第三方接口', res)
})

二、拦截器

在调用 Taro.request 发起请求之前,调用 Taro.addInterceptor 方法为请求添加拦截器,拦截器的调用顺序遵循洋葱模型。

拦截器是一个函数,接受 chain 对象作为参数。chain 对象中含有 requestParmas 属性,代表请求参数。拦截器内最后需要调用 chain.proceed(requestParams) 以调用下一个拦截器或发起请求。

// src/servers/interceptors.js
import { getNewToken } from "./servers";
const customInterceptor = (chain) => {
  const requestParams = chain.requestParams;
  return chain.proceed(requestParams).then((res) => {
    console.log(`http <-- ${url} result:`, res)
    return res
    // 对返回的信息做处理    
  })
};

比如 token 过期、请求服务器异常等问题。

Taro 提供了两个内置拦截器 logInterceptor 与 timeoutInterceptor,分别用于打印请求的相关信息和在请求超时时抛出错误。

Taro.addInterceptor(Taro.interceptors.logInterceptor)
Taro.addInterceptor(Taro.interceptors.timeoutInterceptor)
Taro.request({ url })

当然我们可以将拦截器放在一个数组中,代码如下:

const interceptors = [customInterceptor, Taro.interceptors.logInterceptor];

export default interceptors;

在加载请求方式中,采用 forEach 对拦截器中的每一项进行循环添加。

你可能感兴趣的:(Taro)