fetch 本身无内置适配器机制,但可通过函数或类封装实现类似功能:统一配置、请求/响应拦截、错误处理及插件式扩展,本质是业务层封装而非底层引擎替换。

JavaScript 中 Fetch 本身不提供“请求适配器”这一概念(那是 Axios 等库的设计),所以严格来说,Fetch 没有内置的适配器机制。但你可以通过封装和中间逻辑,模拟出类似适配器的行为——即在发起请求前统一修改配置、拦截请求、处理响应或注入通用逻辑。
用函数封装实现适配器逻辑
最常用的方式是写一个自定义的 fetch 函数,把通用配置(如 base URL、headers、认证 token)和预处理逻辑集中管理:
- 统一添加 Authorization 头、Content-Type 或超时控制
- 自动序列化 body(比如对对象自动转 JSON)
- 对特定错误状态(如 401)触发登出或刷新 token
- 支持传入额外的适配器函数,用于动态修改 request 或 response
示例:
const createFetcher = (defaultOptions = {}) => {
return async (input, options = {}) => {
const config = {
...defaultOptions,
...options,
headers: {
'Content-Type': 'application/json',
...defaultOptions.headers,
...options.headers
}
};
// 适配器:允许外部传入 request 修改逻辑
if (typeof options.requestAdapter === 'function') {
const adapted = await options.requestAdapter(input, config);
input = adapted.input;
config = adapted.config;
}
const res = await fetch(input, config);
// 适配器:响应后处理(如自动解析 JSON、错误映射)
if (typeof options.responseAdapter === 'function') {
return options.responseAdapter(res);
}
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
};
};
// 使用
const api = createFetcher({ baseUrl: '/api' });
api('/users', {
requestAdapter: async (url, config) => ({
input: `${config.baseUrl}${url}`,
config: { ...config, credentials: 'include' }
}),
responseAdapter: async (res) => {
const data = await res.json();
return { success: res.ok, data };
}
});
用类封装 + 插件式适配器链
如果需要更灵活的扩展能力(比如多个适配器按顺序执行),可以设计一个轻量级 FetchClient 类:
- 维护一个适配器数组,每个适配器接收 request 配置并返回新配置
- 支持请求前(onRequest)、响应后(onResponse)、错误时(onError)钩子
- 适配器可复用,例如 authAdapter、loggingAdapter、retryAdapter
示例结构:
class FetchClient {
constructor() {
this.adapters = [];
}
use(adapter) {
this.adapters.push(adapter);
}
async fetch(input, init = {}) {
let request = { input, init };
// 执行所有请求适配器
for (const adapter of this.adapters) {
if (adapter.onRequest) {
request = await adapter.onRequest(request);
}
}
try {
const res = await fetch(request.input, request.init);
let response = { res };
for (const adapter of this.adapters) {
if (adapter.onResponse) {
response = await adapter.onResponse(response);
}
}
return response.res.ok ? response.res.json() : Promise.reject(res);
} catch (err) {
for (const adapter of this.adapters) {
if (adapter.onError) {
await adapter.onError(err, request);
}
}
throw err;
}
}
}
常见适配器场景与写法
实际开发中,这些适配器很实用:
- 认证适配器:从 localStorage 读 token,注入到 Authorization header
- URL 适配器:自动拼接 API 基础路径,支持环境变量切换(dev/staging/prod)
- 重试适配器:对网络失败或 5xx 响应自动重试(带指数退避)
- 日志适配器:打印请求路径、耗时、状态码,仅在开发环境启用
每个适配器保持单一职责,通过组合方式复用,避免污染核心 fetch 调用。
注意与 Axios 的关键区别
Axios 的 adapter 是底层替换 HTTP 发送机制(比如用 Node.js 的 http 模块替代 XMLHttpRequest),而 Fetch 的“适配器”本质是业务层封装。你无法像 Axios 那样替换 fetch 引擎本身,但完全可以通过 wrapper 满足绝大多数定制需求。不需要引入额外库,纯 JS 即可实现清晰、可测试、可维护的请求逻辑。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











