javascript中推荐用class extends实现网络请求类派生,基类封装通用逻辑,子类通过super调用复用并扩展行为,避免原型链继承以确保实例隔离,组合模式适用于需灵活替换底层请求器的场景。

JavaScript 中实现网络请求类的派生,核心是让自定义请求类复用基础请求能力(如统一 baseURL、拦截器、错误处理),同时支持扩展行为(如添加 token、重试逻辑、日志上报)。这不依赖“类必须抽象”,而在于继承结构能否清晰分离通用逻辑与业务逻辑。
用 class extends 实现基础请求类派生
ES6 class 是当前最推荐的方式,语义清晰、支持 super 调用、天然兼容 TypeScript。
- 定义基类 BaseRequest,封装通用 fetch 封装、默认配置、请求/响应拦截骨架
- 子类 AuthRequest 继承 BaseRequest,在构造函数中调用 super(),并在 send 方法中注入 Authorization 头
- 子类可覆盖父类方法(如 handleError),也可新增方法(如 refreshToken)
示例:
class BaseRequest {
constructor(options = {}) {
this.baseURL = options.baseURL || '';
this.timeout = options.timeout || 5000;
}
async send(url, config = {}) {
const fullUrl = this.baseURL + url;
const opts = { ...config, method: config.method || 'GET' };
try {
const res = await fetch(fullUrl, opts);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
return this.handleError(err);
}
}
handleError(err) {
console.warn('Base request error:', err.message);
throw err;
}
}
class AuthRequest extends BaseRequest {
constructor(options) {
super(options);
this.token = options.token || localStorage.getItem('token');
}
async send(url, config = {}) {
const authConfig = {
...config,
headers: {
...config.headers,
'Authorization': `Bearer ${this.token}`
}
};
return super.send(url, authConfig); // 复用父类逻辑
}
async refreshToken(newToken) {
this.token = newToken;
localStorage.setItem('token', newToken);
}
}
避免原型链继承用于请求类派生
手动操作 prototype 或 __proto__ 来模拟继承,对请求类这类有状态、需实例隔离的工具类风险极高:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 无法保证每次 new 都获得独立的配置对象(如 baseURL、token),容易因共享引用导致并发请求串扰
- 拦截器函数若挂载在原型上,多个子类实例会共用同一套回调,难以按实例定制行为
- 错误堆栈和调试体验差,Chrome DevTools 中难以识别真实类名
组合优于继承:部分场景更适合用委托
当子类差异集中在“如何发请求”而非“请求本身是什么”时,组合更灵活:
- 不继承 BaseRequest,而是把 BaseRequest 实例作为私有字段持有
- 对外暴露相同接口(如 send),内部调用 this.client.send()
- 便于运行时切换底层 client(比如从 fetch 换成 axios,或 mock client 用于测试)
例如:LoggingRequest 可包装任意请求器,只负责打日志,不改变请求本质。
注意构造函数参数传递与初始化时机
请求类常需提前配置(如 token、超时、拦截器),务必确保:
- 子类构造函数中显式调用 super(options),不能遗漏
- 若需异步初始化(如从 localStorage 异步读 token),应提供 init() 方法,而非在 constructor 里 await(constructor 不支持 async)
- 避免在原型方法中直接访问未在构造阶段初始化的实例属性,防止 undefined 错误
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










