拦截器

Tuesday, December 20, 2022

拦截器

实例化请求

import Request from './request'

const wxRequest = new Request()

请求拦截

添加token

wxRequest.interceptors.request.use(config => {
  config.header['ACCESS_TOKEN'] = wx.getStorageSync('token');
  return config
})

响应拦截

刷新token

let tokenRequestPromise = null; // [刷新请求]的状态
let isRefreshing = false; // 是否在处理[刷新请求]

function createTokenRequest() {
    // ... 模拟刷新请求token
}

async function refreshToken() {
    if(!isRefreshing) {
        isRefreshing = true
        // tokenRequestPromise被直接赋值为request返回的Promise,与finally无关。 finally为promise的最终回调
        tokenRequestPromise = createTokenRequest().finally(() => {
            isRefreshing = false
        })
    }
    return tokenRequestPromise
}

wxRequest.interceptors.response.use(async (response) => {
  if (response?.data?.code === 2001) { // 假设为token过期/失效
    await refreshToken() // 等待刷新完成,所有请求均等待同一个请求的Promise,不会重复
    const config = response.config
    return wxRequest.request(config) // 重新请求返回新的Promise(Promise链式反应,所以可以直接往外抛)
  }
  return Promise.resolve(response); // 非token失效,正常返回
});

错误重试

wxRequest.interceptors.response.use(async (response) => {
  if (response?.data?.success === false) {
    const config = response.config
    if (!config || !config.retry) {     // 检查配置
      return Promise.reject(response.data);
    }
      
    config.__retryCount = config.__retryCount || 0; // 初始化重试计数
      
    if (config.__retryCount >= config.retry) {  // 判断是否超过重试次数
      return Promise.reject(response.data);
    }

    config.__retryCount += 1;     // 增加重试计数
    
    const backoff = new Promise(resolve => { // 延时处理
      setTimeout(resolve, config.retryDelay || 1000);
    });

    await backoff; // 等待延迟后重新发起请求

    return wxRequest.request(config); // 重新发起请求
  }
  return response; // 返回处理后的响应
});