umi-request全局响应拦截器

文章目录

  • 介绍
  • 思路
  • 实现
    • [方法1.直接修改 umi-request](#方法1.直接修改 umi-request)
    • [方法2.自定义 request 实例,通过 umi-request 库进行配置](#方法2.自定义 request 实例,通过 umi-request 库进行配置)

介绍

后端设计统一返回比如BaseResponse对象,前端也需要接收这个对象,从data取出想要的返回值。

前端请求比如之前返回的是number类型:

当返回参数类型变成BaseResponse,代码也需要更改:

很多请求方法都需要修改,一一修改不仅麻烦还可能容易漏改。因此我们同样可以整一个全局响应拦截器先来处理返回的BaseResponse,如果请求返回成功则取出data返回,如果请求返回失败则直接抛出一个异常外部进行catch,这样我们的请求仍然可以按照之前的写法无需更改。

思路

查看源码:request 里面的 RequestConfig 接口有 responseInterceptors 参数即响应拦截器,

这里创建了类型为 RequestConfigconfig变量,

然后根据 config 变量设置request

因此这里我们尝试在config配置responseInterceptors

通过追溯源码定义 responseInterceptors

直接抄:发送请求打印响应

目测还算成功,起码拦截到了。但是有一个问题:我在源码里修改代码,而这个文件位于 .umi 目录,这个目录是框架生成的,每次重新启动项目这个文件就会恢复原样(相当于白改),因此我们不能在这儿改。

实现

方法1.直接修改 umi-request

直接在app.tsx全局入口文件中,配置全局的request,编写自己的响应处理逻辑。请求返回成功使用resolve方法;请求返回失败使用reject方法,外部方法用try catch捕获,可参考上面的注册方法。

java 复制代码
export const request: RequestConfig = {
  baseURL: '/api',
  timeout: 30000,
  // 自定义全局响应拦截器
  responseInterceptors: [
    // @ts-ignore
    function <T extends AxiosResponse<T, any> = any>(response: AxiosResponse<T>): WithPromise<AxiosResponse<T>> {
      console.log('全局响应拦截器', response);
      console.log('全局响应拦截器', response.data);
      if (response.data.code === 0){
        return Promise.resolve(response.data);
      }
      if (response.data.code === 40100) {
        message.error('请先登录');
        history.replace({
          pathname: '/user/login',
          search: stringify({
            redirect: location.pathname,
          }),
        });
        return Promise.reject(new Error('未登录'));
      } else {
        console.log('全局响应拦截器', response.data.description);
        // @ts-ignore
        return Promise.reject(new Error(response.data.description || '请求出错'));
      }
    }
  ]
};

注:这里返回响应的时候看着点,别返回错了!!!!!!!!!!!!!!!!

可参考下面的request源码:

我们可以看到 request 最终返回的是一个 Promise 对象,使用 resolve方法的时候返回的是 res.data

可配合请求打印响应拦截器的 response 输出日志:

最初的response没有做任何处理响应状态码200。response.data其实就是后端统一封装的返回对象比如BaseResponse。

=========================================================================================

因此这里自定义的全局响应拦截器返回的应该是response.data,而不是response.data.data,因为request最终返回的是Promise对象,返回的是上面的 res.data。简而言之就是人家帮我们取了一层 data 属性,我们返回他的上一级即可,不然取到的可能是undefined(别问我怎么知道的呜呜呜,不看源码一辈都不知道,后来想想也不难理解了,正常我们一般请求返回的响应直接拿到了结果,其实就是取的原始的response.data)。

//这里返回什么也不是绝对的,自定义拦截器的内部逻辑还是要看自己怎么设计的

方法2.自定义 request 实例,通过 umi-request 库进行配置

java 复制代码
import {extend, RequestMethod} from 'umi-request';
import {message} from "antd";
import {history} from "@@/core/history";
import {stringify} from "querystring";

/**
 * 配置request请求时的默认参数
 */
const request: RequestMethod<true> = extend({
  credentials: 'include', // 默认请求是否带上cookie
  prefix: process.env.NODE_ENV === 'production' ? 'TODO' : 'http://localhost:8000/api',
});

/**
 * 所有请求拦截器
 */
request.interceptors.request.use((url, options): any => {
  console.log(`do request url = ${url}`)
  return {
    url,
    options: {
      ...options,
      headers: {},
    },
  };
});

/**
 * 所有响应拦截器
 */
request.interceptors.response.use(async (response): Promise<any> => {
  const res = await response.clone().json();
  if (res.code === 0) {
    return res.data;
  }
  if (res.code === 40100) {
    history.replace({
      pathname: '/user/login',
      search: stringify({
        redirect: location.pathname,
      }),
    });
    message.error('未登录');
  } else {
    message.error(res.description);
  }
  return res;
});

export default request;

与方式1不同,这个直接返回res.data即是我们要的data。

使用时比如api.tsx文件的 request 依赖引入改成自定义的request

相关推荐
空中海1 天前
01 React Native 基础、核心组件与布局体系
javascript·react native·react.js
空中海1 天前
05 React架构设计、项目实践与专家清单
前端·react.js·前端框架
空中海1 天前
04 工程化、质量体系与 React 生态
前端·ubuntu·react.js
空中海1 天前
03 性能、动画与 React Native 新架构
react native·react.js·架构
空中海1 天前
02 React Native状态、导航、数据流与设备能力
javascript·react native·react.js
空中海1 天前
04 React Native工程化、质量、发布与生态选型
javascript·react native·react.js
郑生zs1 天前
Hooks-useEffect
react.js
光影少年1 天前
react函数组件、类组件、纯组件、受控/非受控组件
前端·react.js·掘金·金石计划
空中海1 天前
05 React Native架构设计、主线项目与专家实践
javascript·react native·react.js
killerbasd2 天前
还是迷茫 5.3
前端·react.js·前端框架