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捕获,可参考上面的注册方法。

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 库进行配置

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

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值