基于微信小程序wx.request封装,仿照 axios 的写法,实现请求响应拦截

588 阅读2分钟

在微信小程序原生开发过程中发现 wx.request 没有请求响应拦截的功能,所有参照 axios 对 wx.request进行简单的封装

/*
* 请求方式的枚举
*/
export enum HttpMethod {
  GET = "GET",
  HEAD = "HEAD",
  POST = "POST",
  PUT = "PUT",
  DELETE = "DELETE",
  OPTIONS = "OPTIONS",
  TRACE = "TRACE",
  CONNECT = "CONNECT"
}

/*
* 请求入参消息
*/
class RequestMessage {
  Api:string;
  Param: any;
  Method: HttpMethod;
  Header: Object;
  constructor(api:string,param:any,method:HttpMethod = HttpMethod.GET,header:any = null){
    this.Api = api;
    this.Param = param;
    this.Method = method;
    this.Header = header;
  }
}

/**
 * HttpClient 实例
 */
class HttpClient {
  private RequestInterceptor: Function | undefined;
  private ReponseInterceptor: Function | undefined;
  private baseUrl: string;
  constructor(baseUrl:string = ''){
    this.baseUrl = baseUrl;
  }
  
  /** 请求拦截器 */
  public UseRequestInterceptor(interceptor:(requestMessage: RequestMessage) => boolean): HttpClient {
    this.RequestInterceptor = interceptor;
    return this;
  }
 
  /** 响应拦截器 */
  public UseReponseInterceptor(interceptor:(reponseMessage:any) => any): HttpClient {
    this.ReponseInterceptor = interceptor;
    return this;
  }
 
  /**
   * 发起请求
   * @param requestMessage 请求体 
   */
  private Request(requestMessage:RequestMessage){ 
    var that = this;
    return new Promise((resolve,reject) => {
      if(that.RequestInterceptor && !that.RequestInterceptor(requestMessage))
        return reject("取消请求");
      wx.request({
        url: `${that.baseUrl}${requestMessage.Api}`,
        data:requestMessage.Param,
        method: requestMessage.Method,
        header:requestMessage.Header,
        success(res) {
          resolve && resolve(that.ReponseInterceptor && that.ReponseInterceptor(res));
        },
        fail(error){ 
          reject && reject(error);
         }
      });
    });
  }
 
  /**
   * Get 请求
   * @param api 接口
   * @param param 入参
   */
  public Get(api: string, param: any) {
    return this.Request(new RequestMessage(api,param));
  }
 
  /**
   * Head 请求
   * @param api 
   * @param param 
   * @returns 
   */
  public Head(api: string, param: any){
    return this.Request(new RequestMessage(api,param,HttpMethod.HEAD));
  }
 
  /**
   * Post 请求
   * @param api 接口 
   * @param param 入参
   */
  public Post(api: string, param: any){
    return this.Request(new RequestMessage(api,param,HttpMethod.POST));
  }
 
  /**
   * Connect 请求
   * @param api 
   * @param param 
   * @returns 
   */
  public Connect(api: string,param:any){
    return this.Request(new RequestMessage(api,param,HttpMethod.CONNECT));
  }
 
  /**
   * OPTIONS 请求
   * @param api 
   * @param param 
   * @returns 
   */
  public Options(api: string,param:any){
    return this.Request(new RequestMessage(api,param,HttpMethod.OPTIONS));
  }
 
  /**
   * Delete 请求
   * @param api 接口
   * @param param 入参
   */
  public Delete(api: string,param?: any){
    return this.Request(new RequestMessage(api,param,HttpMethod.DELETE));
  }
 
  /**
   * Put 请求
   * @param api 接口
   * @param param 入参
   */
  public Put(api: string, param: any){
    return this.Request(new RequestMessage(api,param,HttpMethod.PUT));
  }
}
 
/** HttpClient工厂 */
export class HttpClientFactory{
  public static Create(baseUrl:string = ''): HttpClient{
    return new HttpClient(baseUrl);
  }
}

以上就是对于 wx.request 的封装,但是还是有缺陷,同一个 HttpClient 实例对象的拦截器多次注册只有最后一次注册的会起作用。(如果有需要这里可以直接变更,将 RequestInterceptor | ReponseInterceptor 改成数组,注册的时候不断把拦截器push到数组中,在拦截器执行的时候依次执行拦截器,或者如果有权重可以先排序后依次执行)

使用

import { HttpClientFactory } from '@/utils/request';
import { StatusCode } from '@/enums/httpstatus-enum';
import * as StorageConst from '@/consts/storage-const';

export const client = HttpClientFactory.Create('http://127.0.0.1:5000/api/');

/* 
* 注册请求拦截器 
*/
client.UseRequestInterceptor(requestMessage => {
  if(requestMessage.Api !== "auth/login"){
    requestMessage.Header =  {
      "Authorization" : wx.getStorageSync(StorageConst.BearerToken)
    };
  }
  return true;
});

/* 
* 注册请求拦截器 
*/
client.UseReponseInterceptor(reponseMessage => {
  reponseMessage&&console.log(reponseMessage);
  switch(reponseMessage.statusCode){  
    case StatusCode.StatusCode200Ok:
      return reponseMessage.data;
    case StatusCode.StatusCode401NotAuthorization:
      wx.redirectTo({ url :'../auth/login/index'});
      return;
      case StatusCode.StatusCode404NotFound:
      wx.showToast(reponseMessage.statusCode)
      return;
    default:
      return "状态码异常";
  }
});

// apis/i-auth-service.js 文件

import { client } from '@/utils/http-client';
import { LoginInput } from '@/api/i-auth-service';
import * as StorageConst from '@/consts/storage-const';
 
/**
 * 登录
 * @param options 
 */
export function Login(options:LoginInput) {
  client.Post('auth/login',options).then(res => {
    wx.setStorageSync(StorageConst.BearerToken, `Bearer ${res.data}` );
    console.log(res);
  }).catch(reason => {
    console.log(reason);
  });
}