重构 xmlhttprequest 网络层需分阶段解耦封装、渐进升级,统一请求入口与响应契约,标准化错误分类,预留 fetch/axios 适配层,并通过工厂函数、类 promise 接口和灰度迁移保障兼容性与可维护性。

重构遗留系统网络层时,基于 XMLHttpRequest 的 onreadystatechange 异步模型,核心不是推倒重来,而是分阶段解耦、封装和渐进升级。重点在于保留兼容性的同时,提升可维护性、错误可观测性和调用一致性。
明确重构目标与边界
先厘清“为什么重构”:老旧代码常存在硬编码 URL、重复创建 XHR 实例、状态判断不严谨(如只判 readyState === 4 忽略 status)、错误处理缺失或全靠 alert 等问题。重构目标应聚焦三点:
- 统一请求入口,剥离业务逻辑与网络细节
- 标准化状态流转和错误分类(网络失败、HTTP 错误、解析异常)
- 为后续迁移到
fetch或 Axios 预留适配层,避免强绑定原生 XHR
封装 XHR 生命周期为可复用构造函数
参考知识库中 net.ContentLoader 的思路,但需现代化改进:去掉 IE6 兼容包袱(除非必须支持),使用标准构造方式,并引入配置项收敛行为。
- 用工厂函数替代全局
new XMLHttpRequest(),便于后期替换底层实现 - 将
open、setRequestHeader、send封装进实例方法,避免裸调用散落各处 -
onreadystatechange回调内严格检查readyState === 4且status在 200–299 范围,否则归为 HTTP 错误 - 响应数据默认尝试
JSON.parse,捕获语法错误并抛出结构化错误对象
抽象统一的请求接口与响应契约
定义最小可用 API,例如 request({ url, method = 'GET', data, headers }),返回一个带 then/catch 的类 Promise 对象(不必是真 Promise,但语义一致)。
- 所有请求参数通过对象传入,禁止拼接 URL 字符串或手动设置
Content-Type - 自动识别
data类型:对象则序列化为application/json;字符串或 FormData 则保持原样 - 响应统一格式:
{ data: parsedBody, status, statusText, headers },无论成功或失败都走同一结构 - 超时、网络中断、跨域拒绝等非 HTTP 错误,统一映射为特定错误码(如
ERR_NETWORK),便于上层分类处理
渐进式替换与测试保障
不追求一次性全部替换,而是按模块/页面灰度切换:
- 新功能一律使用新封装层;旧功能在修复 bug 时同步迁移
- 为老代码添加薄层适配器,例如
legacyAjax(url, callback)内部调用新 request 并桥接回调 - 关键路径补充单元测试:模拟不同
readyState变化、各种status值、空响应、非法 JSON 等边界情况 - 利用浏览器 DevTools 的 Network 面板验证请求头、重试逻辑、缓存控制是否符合预期










