JavaScript 全局监听所有 Ajax 请求事件的方法
当项目中存在大量由原生 JavaScript 发起的 Ajax 请求,且无法修改底层代码时,传统的全局监听方法失效。本文提供基于重写 XMLHttpRequest 构造函数的方案,配合浏览器原生事件机制,实现对所有 Ajax 请求状态的统一捕获与分析。
背景与问题分析
在 Web 开发中,监听 Ajax 请求通常用于日志记录、性能分析或全局错误处理。如果使用 jQuery,开发者可以直接利用其提供的 Global Ajax Event Handlers(如 .ajaxSend()、.ajaxComplete())。然而,这些方法仅对通过 $.ajax 发起的请求有效。
对于使用原生 JavaScript(XMLHttpRequest)或第三方 HTTP 库发起的请求,若无法侵入源码添加发布/订阅(Pub/Sub)逻辑,则需采用底层拦截手段。常见的误区是直接替换原型链上的 open 和 send 方法,但这会导致状态监听滞后或丢失部分事件细节。
核心原理:重写构造函数与自定义事件
正确的做法是保存原始的 XMLHttpRequest 构造函数,然后创建一个新的构造函数 newXHR。在新构造函数中实例化原始对象,并利用 addEventListener 为实例绑定原生 XHR 事件,将这些原生事件重新包装为自定义事件(CustomEvent),并通过 window.dispatchEvent 派发出去。这样,外部代码只需监听 window 上的自定义事件即可。
第1步:实现无兼容性限制的通用代码
首先定义一个触发事件的辅助函数,它接收事件名并将当前的 XHR 对象作为 detail 传递给自定义事件。
(function() {
function ajaxEventTrigger(event) {
var ajaxEvent = new CustomEvent(event, { detail: this });
window.dispatchEvent(ajaxEvent);
}
var oldXHR = window.XMLHttpRequest;
function newXHR() {
var realXHR = new oldXHR();
// 绑定原生 XHR 事件并转换为自定义事件
realXHR.addEventListener('abort', function () { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false);
realXHR.addEventListener('error', function () { ajaxEventTrigger.call(this, 'ajaxError'); }, false);
realXHR.addEventListener('load', function () { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false);
realXHR.addEventListener('loadstart', function () { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false);
realXHR.addEventListener('progress', function () { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false);
realXHR.addEventListener('timeout', function () { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false);
realXHR.addEventListener('loadend', function () { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false);
realXHR.addEventListener('readystatechange', function() { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false);
return realXHR;
}
// 覆盖全局 XMLHttpRequest 构造函数
window.XMLHttpRequest = newXHR;
})();
第2步:添加旧版浏览器支持 (Polyfill)
上述代码依赖于 ES5 的 CustomEvent 构造函数,这在 Internet Explorer(包括 IE11)和部分老旧浏览器中不被直接支持。为确保全平台兼容,需在包裹 XHR 重写逻辑前加入以下 Polyfill:
;(function () {
if ( typeof window.CustomEvent === "function" ) return false;
function CustomEvent ( event, params ) {
params = params || { bubbles: false, cancelable: false, detail: undefined };
var evt = document.createEvent( 'CustomEvent' );
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
return evt;
}
CustomEvent.prototype = window.Event.prototype;
window.CustomEvent = CustomEvent;
})();
将此 Polyfill 置于最前,随后执行上述 XHR 重写代码,即可支持 IE9+、Chrome 15+、Firefox 11+、Edge、Safari 6.1+ 等主流环境。
调用方法与注意事项
完成配置后,其他脚本可以通过监听 window 上的自定义事件来获取 Ajax 信息。与普通 DOM 事件不同,自定义事件的 event.detail 属性包含真正的 XMLHttpRequest 对象实例。
var xhr = new XMLHttpRequest();
// 监听 readyState 变化
window.addEventListener('ajaxReadyStateChange', function (e) {
console.log('Request State:', e.detail.readyState);
});
// 监听错误并获取响应内容
window.addEventListener('ajaxError', function (e) {
// 注意:必须通过 e.detail 访问 XHR 对象
console.log('Response Text:', e.detail.responseText);
});
xhr.open('GET', 'info.json');
xhr.send();
关键差异说明
- 对象获取路径:常规 XHR 事件中,
this指向 XHR 对象;而在本方案的自定义事件中,事件对象e是CustomEvent,真实 XHR 对象位于e.detail。例如,获取响应文本应写为e.detail.responseText而非e.responseText。 - 事件挂载位置:监听器必须挂载在
window对象上。因为xmlhttprequest实例是由被重写的构造函数创建的,它们内部触发的自定义事件已主动派发到window。
以上就是 JavaScript 监听全部 Ajax 请求事件的详细内容,更多关于 JavaScript 网络请求监控的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













