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

相关推荐
用户305875848912538 分钟前
Connected-react-router核心思路实现
react.js
哑巴语天雨15 小时前
React+Vite项目框架
前端·react.js·前端框架
初遇你时动了情15 小时前
react 项目打包二级目 使用BrowserRouter 解决页面刷新404 找不到路由
前端·javascript·react.js
码农老起16 小时前
掌握 React:组件化开发与性能优化的实战指南
react.js·前端框架
前端没钱16 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
高山我梦口香糖19 小时前
[react] <NavLink>自带激活属性
前端·javascript·react.js
撸码到无法自拔19 小时前
React:组件、状态与事件处理的完整指南
前端·javascript·react.js·前端框架·ecmascript
高山我梦口香糖19 小时前
[react]不能将类型“string | undefined”分配给类型“To”。 不能将类型“undefined”分配给类型“To”
前端·javascript·react.js
乐闻x1 天前
VSCode 插件开发实战(四):使用 React 实现自定义页面
ide·vscode·react.js
irisMoon061 天前
react项目框架了解
前端·javascript·react.js