闭包和柯里化是提升api封装灵活性与复用性的关键设计手段:闭包固化baseurl、headers等通用配置,柯里化分步接收方法、路径、参数,二者结合支持中间件扩展与渐进式调用。

闭包和柯里化不是炫技工具,而是让 API 封装更灵活、可复用的关键设计手段。一个通用的请求封装器,核心在于:固定通用配置(如 baseURL、headers),动态传入变化部分(如路径、参数、方法),同时支持按需扩展行为(如鉴权、错误重试、日志)。闭包负责“记住”初始配置,柯里化负责“分步接收”参数,二者结合,自然产出高内聚、低耦合的请求函数。
用闭包固化基础配置
闭包让封装器能预先保存环境信息,比如统一的 base URL、默认超时、认证 token 或公共 headers。这些值在初始化时确定,后续每次调用都自动携带,无需重复传入。
- 创建一个工厂函数(如 createRequester),接收配置对象作为参数
- 内部定义实际发起请求的函数(如 request),它能访问外部作用域的配置
- 返回这个内部函数——它“封闭”了配置,形成闭包
这样,createRequester({ baseURL: 'https://api.example.com' }) 返回的函数,天生就知道该往哪发请求。
用柯里化拆解请求参数
柯里化把多参数函数转为一系列单参数函数,便于组合与复用。对请求来说,可把“方法 + 路径”作为第一层,“查询参数或 body”作为第二层,“额外选项(如 signal、cache)”作为第三层。
- 例如:get('/users') 返回一个等待 params 的函数;再传 { id: 123 },才真正发起 GET /users?id=123
- 类似地,post('/login')(credentials) 把接口路径和提交数据分离,方便复用路径逻辑
- 柯里化后,还可轻松派生专用函数:const fetchUser = get('/users'),后续只关心用户 ID
组合中间件与运行时增强
闭包提供的上下文,是插入拦截逻辑的理想位置。比如自动注入 token、统一处理 401、添加请求 ID 日志等,都不需要修改每次调用的代码。
- 在闭包内维护一个中间件队列(如 use(fn) 方法),每个 fn 接收 config 和 next
- 柯里化后的请求函数执行时,先遍历中间件链,最后才调用原生 fetch
- 例如:token 中间件读取 localStorage,自动加到 headers;错误中间件捕获 401 后触发登出
这种结构下,业务层调用仍是简洁的 fetchUser({ id: 1 }),而安全、日志、重试等能力已静默集成。
实战:一个轻量但完整的封装器
下面是一个基于 fetch 的简化实现,融合闭包与柯里化:
const createRequester = (config) => {
const { baseURL, headers = {}, timeout = 5000 } = config;
// 中间件存储
const middlewares = [];
const use = (fn) => middlewares.push(fn);
// 柯里化主请求函数
const request = (method) => (path) => async (data, options = {}) => {
const url = new URL(path, baseURL);
const init = {
method,
headers: { ...headers, ...options.headers },
signal: options.signal,
...options,
};
if (method === 'GET' && data) {
Object.keys(data).forEach(k => url.searchParams.append(k, data[k]));
} else if (['POST', 'PUT', 'PATCH'].includes(method) && data) {
init.body = JSON.stringify(data);
init.headers['Content-Type'] = 'application/json';
}
// 执行中间件链
const run = (cfg) => middlewares.reduceRight(
(next, fn) => () => fn(cfg, next),
() => fetch(url, init)
);
return run({ url, method, data, options });
};
// 提供常用方法的柯里化别名
return {
get: request('GET'),
post: request('POST'),
put: request('PUT'),
delete: request('DELETE'),
use,
};
};
// 使用示例
const api = createRequester({ baseURL: 'https://api.example.com' });
api.use((config, next) => {
const token = localStorage.getItem('token');
if (token) config.headers.Authorization = `Bearer ${token}`;
return next();
});
const fetchProfile = api.get('/users/me');
fetchProfile().then(res => res.json()).then(console.log);
不复杂但容易忽略:闭包让配置“活”在函数内部,柯里化让调用“渐进式”展开——两者配合,才能写出既健壮又易用的请求工具。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











