javascript中fetch api本身不支持拦截器,但可通过函数封装+中间件链模拟:请求拦截器修改input/init(如加token),响应拦截器处理response(如判状态码、解析json),支持异步、中断及链式执行。

JavaScript 中 Fetch API 本身不支持拦截器(interceptor)机制,不像 Axios 那样内置 request/response 拦截能力。但可以通过封装一层函数、利用 Promise 链或构建自定义 fetch 工厂来模拟 interceptor 行为,实现请求前处理(如加 token)、响应后统一处理(如错误解析、重试)等扩展功能。
用函数封装 + 中间件链模拟拦截器
核心思路是把 fetch 调用“包”进一个可插拔的中间件管道中,每个中间件接收 config(请求配置)和 next(下一个中间件),最后调用原生 fetch。
- 定义一个
createFetch工厂函数,接受多个拦截器(request 和 response 分开或合并) - request 拦截器在发起请求前修改
input或init(如添加 headers、序列化 body) - response 拦截器在
fetch().then()后处理响应(如检查 status、自动解析 JSON、抛出业务错误) - 拦截器按顺序执行,支持异步(
async/await),且可中断流程(例如未登录时跳过请求)
一个轻量实用的拦截器实现示例
下面是一个简洁、可复用的拦截器封装(无依赖):
function createInterceptedFetch(...interceptors) {
return async function(input, init = {}) {
// 构建中间件链:从 request → fetch → response
const runRequestInterceptors = (input, init) =>
interceptors.reduceRight(
(next, interceptor) => async () => {
if (interceptor.request) {
const result = await interceptor.request(input, init, next);
return result ?? next();
}
return next();
},
() => fetch(input, init)
);
const runResponseInterceptors = (response) =>
interceptors.reduce(
(prev, interceptor) => async () => {
if (interceptor.response) {
return interceptor.response(await prev(), response.clone());
}
return prev();
},
() => Promise.resolve(response)
);
const rawResponse = await runRequestInterceptors(input, init);
return runResponseInterceptors(rawResponse)();
};
}
// 使用示例:添加 auth header 和统一错误处理
const myFetch = createInterceptedFetch({
request: async (input, init) => {
const token = localStorage.getItem('token');
if (token && !init.headers) init.headers = {};
if (token) init.headers['Authorization'] = `Bearer ${token}`;
}
}, {
response: async (prevRes, res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
const json = await res.json();
if (json.code !== 0) throw new Error(json.message || '请求失败');
return json.data;
}
});
常见扩展场景与写法建议
实际项目中,拦截器常用于以下场景,注意细节避免陷阱:
- 自动刷新 token:在 response 拦截器中检测 401,先调用刷新接口,再重发原请求(需保存原始 config 并重建 fetch)
- 请求日志 & 性能监控:request 拦截器打点开始时间,response 拦截器计算耗时并上报
- 缓存控制:request 拦截器根据 URL 或 header 决定是否走本地缓存(如 Map 存 Response clone)
- 全局 loading 状态:配合 UI 框架,在 request 拦截器触发 loading 开启,response 拦截器关闭(注意异常也要关)
为什么不直接 monkey patch window.fetch?
虽然可以覆盖 window.fetch 实现全局拦截,但不推荐:
- 破坏环境纯净性,影响其他库(如某些 SDK 自带 fetch 封装)
- 难以做多实例隔离(比如测试环境需要 mock,生产环境要真实请求)
- 调试困难,堆栈里看不到原始调用位置
- 不符合现代前端模块化与可组合设计思想
更合理的方式是显式创建受控的 fetch 实例(如 apiClient.fetch),便于测试、替换和维护。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











