UniApp 网络请求不好用,那就封装一个丐版Axios

201 阅读2分钟

uniapp网络请求功能比较基础, 缺乏请求拦截,响应拦截,所以我封装了一个丐版Axios, 废话不多说, 直接上代码。

// http.js
export default class HttpRequest {
  constructor(baseURL) {
    this.baseURL = baseURL;
    this.interceptors = {
      request: [],
      response: []
    };
  }

  // 添加请求拦截器
  interceptorRequest(fulfil, reject) {
    this.interceptors.request.push({ fulfil, reject });
  }

  // 添加响应拦截器
  interceptorResponse(fulfil, reject) {
    this.interceptors.response.push({ fulfil, reject });
  }

  // 请求方法
  /**
   * 请求方法
   * @param {{url:string, method: 'GET'|'POST'|'PUT'|'DELETE', data: any, header:any}} options
   * @returns {Promise<unknown>}
   */
  async request(options) {
    if(!options.url) {
      options.url  = ''
    }
    // 合并基础配置
    const finalConfig = {
      ...options,
      url: this.baseURL + options.url,
      method: options.method || 'GET',
      header: options.header || { 'content-type': 'application/json' },
    };

    // 应用请求拦截器
    let requestInterceptors = this.interceptors.request;
    for (let interceptor of requestInterceptors) {
      await interceptor.fulfil(finalConfig);
    }

    // 发送请求
    return new Promise((resolve, reject) => {
      uni.request({
        ...finalConfig,
        success: (response) => {
          // 应用响应拦截器
          let responseInterceptors = this.interceptors.response;
          let res = response.data;
          if (response.statusCode < 400) {
            for (let interceptor of responseInterceptors) {
              // 响应拦截器存入请求参数
              res = interceptor.fulfil(res, options);
            }
            resolve(res);
          } else {
            reject(res);
          }
        },
        fail: (error) => {
          // 应用响应拦截器
          let responseInterceptors = this.interceptors.response;
          let err = error;
          for (let interceptor of responseInterceptors) {
            err = interceptor.reject(err);
          }
          reject(err);
        }
      });
    });
  }

  // 单例模式获取实例
  static getInstance(baseURL) {
    if (this.instance) {
      return this.instance;
    } else {
      this.instance = new HttpRequest(baseURL);
      return this.instance;
    }
  }
}

接下来对http.js进行简单封装, 方便使用。

// request.js
import HttpRequest from './http.js';

export const request = (options = {}) => {
    const http = HttpRequest.getInstance(import.meta.env.VITE_APP_BASE_API);
    http.interceptorRequest((config) => {
        // 添加拦截代码
        return config;
    }, (error) => {
        console.error('Request Error:', error);
        return error;
    });
    // 响应拦截器传入请求参数
    http.interceptorResponse((response, config) => {
        // 对响应数据做点什么
        // 示例业务代码
        if (response.code === -998) {
            // 登录过期
            return new Promise((resolve, reject) => {
                - addRequest(() => resolve(http.request(options)))
                + addRequest(() => resolve(http.request(config)))
                refreshToken()
            })
        }
        if (!response.ok) {
            uni.showToast({
                title: response?.msg || '请求失败',
                icon: 'none',
            })
            return response
        }
        return response;
    }, (error) => {
        // 对响应错误做点什么
        uni.showToast({
            title: error?.msg || error?.message || '请求失败',
            icon: 'none',
        })
        return Promise.reject(error);
    });

    return http.request(options)
}

长短token无感刷新代码

let subscribes = []
let flag = false // 设置开关,保证一次只能请求一次短token,防止多此操作,多次请求

/*把过期请求添加在数组中*/
export const addRequest = (request) => {
  subscribes.push(request)
}

/*调用过期请求*/
export const retryRequest = () => {
  console.log('重新请求上次中断的数据');
  console.log(subscribes);
  subscribes.forEach(request => request())
  subscribes = []
}

调用refreshToken方法刷新token后, 调用retryRequest方法重新请求上次中断的数据

之前的代码响应拦截保存请求有一处,现已更正