React中能否为fetch请求响应配置过滤器统一处理指定端点逻辑?
React项目统一处理fetch响应Refresh-Token存储方案
完全可以通过封装全局fetch请求层加响应拦截的方式实现,不需要在每个接口单独编写存储逻辑,具体实现如下:
第一步:封装通用请求工具
新建通用请求工具文件,统一处理公共请求逻辑、响应拦截逻辑,内置端点匹配规则,只对配置的接口执行Refresh-Token提取存储操作。
// src/utils/request.js const BASE_URL = process.env.REACT_APP_PROXY; // 配置需要自动提取Refresh-Token的接口匹配规则,支持字符串前缀、正则两种匹配方式 const TOKEN_REFRESH_RULES = [ /^\/users\//, // 示例:匹配所有/users/前缀的接口 // 后续新增接口直接在这里追加规则即可 ]; /** * 校验当前请求地址是否命中Token自动处理规则 * @param {string} requestUrl 完整请求地址 * @returns {boolean} */ const isNeedHandleToken = (requestUrl) => { const apiPath = requestUrl.replace(BASE_URL, ''); return TOKEN_REFRESH_RULES.some(rule => { if (typeof rule === 'string') return apiPath.startsWith(rule); if (rule instanceof RegExp) return rule.test(apiPath); return false; }); }; /** * 封装后的通用请求方法,全局替换原生fetch使用 * @param {string} url 接口路径/完整地址 * @param {object} fetchOptions 原生fetch支持的所有配置项 * @returns {Promise<Response>} 和原生fetch返回一致的Promise对象 */ const request = (url, fetchOptions = {}) => { // 合并默认请求配置 const mergedOptions = { method: 'GET', headers: { 'Content-Type': 'application/json', ...(fetchOptions.headers || {}) }, ...fetchOptions }; // 自动注入鉴权请求头 const storedToken = sessionStorage.getItem('token'); if (storedToken) { mergedOptions.headers.Authorization = `Token ${storedToken}`; } // 拼接完整请求地址 const fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url}`; return fetch(fullUrl, mergedOptions).then(response => { // 统一响应拦截:命中规则、响应正常、存在Refresh-Token头时自动存储 if (response.ok && isNeedHandleToken(fullUrl)) { const refreshToken = response.headers.get('Refresh-Token'); if (refreshToken) { sessionStorage.setItem('token', refreshToken); } } // 将原始响应返回给业务层,保持和原生fetch使用体验一致 return response; }); }; export default request;
第二步:替换业务代码中的原生fetch
所有原有调用原生fetch的地方,直接替换为引入封装好的request方法即可,原有业务逻辑基本不需要改动,重复的公共逻辑全部被封装层收口。
改写后的表单提交示例:
import request from '@/utils/request'; const handleFormSubmit = (e) => { e.preventDefault() if (password != passConfirm) { setErrors({passConfirm: ["Must match password"]}) return } request('/users/', { method: 'POST', body: JSON.stringify({first_name, last_name, username, password, email}) }).then((response) => { if (response.ok) { // 无需再手动编写Refresh-Token存储逻辑 setRedirect(true) } else { setErrors(response) console.log(response) } }) }
方案优势
- 逻辑高度收口:Token存储、鉴权头注入、baseURL拼接等公共逻辑只需要维护一处,后续修改存储方式、鉴权规则不需要改动业务代码
- 配置成本极低:新增需要自动处理Token的接口时,只需要在
TOKEN_REFRESH_RULES数组中追加一条匹配规则即可,不需要侵入业务逻辑 - 扩展性强:后续需要新增统一错误提示、请求loading、超时控制、响应格式转换等全局逻辑时,直接在request封装层添加即可
注意:跨域场景下需要后端在响应头中配置Access-Control-Expose-Headers: Refresh-Token,否则前端无法通过JS读取到自定义的Refresh-Token响应头。
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

