能否用Redux RTK实现拦截器处理错误?还有哪些替代方案?
RTK Query的拦截器替代方案及错误处理方法
RTK Query没有和Axios完全一致的“拦截器”概念,但可以通过以下几种机制实现类似的请求/响应拦截、全局或局部错误处理:
1. 基于Axios自定义baseQuery(直接复用Axios拦截器)
如果习惯Axios的拦截器逻辑,可以把Axios作为RTK Query的底层请求工具,自定义baseQuery后直接配置Axios的请求/响应拦截器。
示例代码:
import axios from 'axios'; import { createApi } from '@reduxjs/toolkit/query/react'; // 配置Axios实例和拦截器 const axiosInstance = axios.create({ baseURL: 'https://api.example.com' }); // 请求拦截器:统一添加请求头 axiosInstance.interceptors.request.use( (config) => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error) ); // 响应拦截器:统一处理错误状态码 axiosInstance.interceptors.response.use( (response) => response, (error) => { if (error.response?.status === 401) { // 处理未授权逻辑,比如清除token、跳转登录页 localStorage.removeItem('token'); window.location.href = '/login'; } return Promise.reject(error); } ); // 自定义Axios版baseQuery const axiosBaseQuery = ({ baseUrl } = { baseUrl: '' }) => async ({ url, method, data, params }) => { try { const result = await axiosInstance({ url: baseUrl + url, method, data, params }); return { data: result.data }; } catch (axiosError) { return { error: { status: axiosError.response?.status, data: axiosError.response?.data || axiosError.message, }, }; } }; // 创建API时使用自定义baseQuery export const api = createApi({ reducerPath: 'api', baseQuery: axiosBaseQuery({ baseUrl: 'https://api.example.com' }), endpoints: (builder) => ({ getPosts: builder.query({ query: () => '/posts', }), }), });
2. 使用RTK Query内置的transformRequest/transformResponse
这两个配置可以在单个endpoint级别,对请求数据(发送前)和响应数据(成功返回后)做转换处理,相当于轻量的请求/响应拦截:
export const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: 'https://api.example.com' }), endpoints: (builder) => ({ createPost: builder.mutation({ query: (postData) => ({ url: '/posts', method: 'POST', body: postData, }), // 请求发送前格式化数据 transformRequest: (postData) => { return { ...postData, createdAt: new Date().toISOString() }; }, // 成功响应后处理返回结果 transformResponse: (responseData) => { return { id: responseData.id, title: responseData.title.toUpperCase() }; }, }), }), });
3. 全局/局部错误处理
全局错误处理
在createApi时包装baseQuery,实现所有请求的错误统一处理:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const baseQuery = fetchBaseQuery({ baseUrl: 'https://api.example.com' }); const baseQueryWithErrorHandling = async (args, api, extraOptions) => { const result = await baseQuery(args, api, extraOptions); if (result.error) { // 全局错误处理逻辑:比如上报错误、弹出提示 console.error('全局捕获错误:', result.error); if (result.error.status === 403) { api.dispatch(logout()); } } return result; }; export const api = createApi({ reducerPath: 'api', baseQuery: baseQueryWithErrorHandling, endpoints: (builder) => ({ /* ... */ }), });
单个请求的错误处理
调用查询/突变钩子时,通过onError回调处理单个请求的专属错误:
const { mutate } = useCreatePostMutation(); const handleCreatePost = (postData) => { mutate(postData, { onError: (error) => { alert(`创建帖子失败: ${error.data.message}`); }, onSuccess: (data) => { // 成功回调逻辑 }, }); };
4. 自动重试机制
RTK Query内置重试功能,可在全局或单个endpoint级别配置,自动重试失败的请求:
// 全局配置重试规则 export const api = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: 'https://api.example.com' }), retry: 3, // 最多重试3次 retryDelay: (retryCount) => retryCount * 1000, // 每次重试间隔递增1秒 endpoints: (builder) => ({ /* ... */ }), }); // 单个endpoint覆盖全局配置 getPosts: builder.query({ query: () => '/posts', retry: 1, // 仅重试1次 }),
内容的提问来源于stack exchange,提问作者Yash
相关产品推荐
相关产品推荐

