如何在JavaScript中实现类似XMLHttpRequest的自定义事件处理器
实现类似XMLHttpRequest的自定义事件处理器
嘿,我懂你要的效果——就是自己搞一个像XMLHttpRequest那样,能通过赋值onxxxx属性来监听多阶段状态变化的事件机制对吧?之前试了addEventListener和Promise没找到感觉,其实核心思路很简单:在自定义类里封装一个可赋值的回调属性,然后在状态变化时主动触发这个回调。
完整实现示例
我们来写一个模拟请求的CustomRequest类,完全复刻XHR的onreadystatechange逻辑:
class CustomRequest { // 私有字段存储回调函数,避免外部直接修改 #onReadyStateChange = null; // 公开的状态属性,对应XHR的readyState readyState = 0; // 模拟HTTP状态码 status = 0; // 定义可外部赋值的onreadystatechange属性 get onreadystatechange() { return this.#onReadyStateChange; } set onreadystatechange(callback) { // 只接受函数类型的赋值,非函数则清空回调 this.#onReadyStateChange = typeof callback === 'function' ? callback : null; // 可选:赋值后立即触发一次当前状态的回调 this.#triggerCallback(); } // 私有方法:触发回调,确保回调里的this指向当前实例 #triggerCallback() { if (typeof this.#onReadyStateChange === 'function') { this.#onReadyStateChange.call(this); } } // 模拟请求发送过程,逐步改变状态 send() { // 状态1:开始加载 this.readyState = 1; this.#triggerCallback(); // 用定时器模拟异步状态变化 setTimeout(() => { this.readyState = 2; // 等待响应 this.#triggerCallback(); setTimeout(() => { this.readyState = 3; // 接收数据中 this.#triggerCallback(); setTimeout(() => { this.readyState = 4; // 请求完成 this.status = 200; // 模拟成功状态码 this.#triggerCallback(); }, 500); }, 500); }, 500); } }
使用方式(和XHR完全一致)
const req = new CustomRequest(); req.onreadystatechange = function() { switch (this.readyState) { case 0: console.log('未初始化'); break; case 1: console.log('加载中'); break; case 2: console.log('等待响应'); break; case 3: console.log('接收数据中'); break; case 4: if (this.status === 200) { console.log('请求成功!'); } break; } }; // 启动模拟请求 req.send();
为什么addEventListener/Promise没满足需求?
- addEventListener:它是基于事件类型的订阅模式,适合多回调场景,但XHR的
onreadystatechange是单一覆盖式的回调(每次赋值会替换之前的函数),和订阅模式逻辑不同; - Promise:它只能处理一次成功/失败的结果,无法适配像readyState这样的多阶段状态变化,所以天然不适合这种需要多次触发回调的场景。
可选优化点
- 如果需要支持多个回调,可以把
#onReadyStateChange改成数组,赋值时push函数,触发时遍历执行; - 可以添加其他类似XHR的回调属性,比如
onload、onerror,逻辑和onreadystatechange一致; - 加入错误捕获,避免回调执行出错导致实例逻辑中断。
内容的提问来源于stack exchange,提问作者Winterhill
相关产品推荐
相关产品推荐

