分享JavaScript监听全部Ajax请求事件的方法

前端之家收集整理的这篇文章主要介绍了分享JavaScript监听全部Ajax请求事件的方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

若Ajax请求是由jQuery的$.ajax发起的,默认情况下可以使用 jQuery的Global Ajax Event Handlers监听到Ajax事件,然而我遇到的却是用原生JavaScript发起的Ajax请求,所以这种方法行不通。

然后呢,还有其他方法,比如说 Pub/Sub,但是这个发起请求的 js 代码我是无法改动的,也就不存在向代码添加 publish 的问题。同理,jQuery 的 .bind.trigger 也无法使用。

最后,决定使用直接 override XMLHttpRequest,同时配合使用自定义事件。

在 StackOverflow 上搜索,发现有个歪果仁给出了一个不靠谱的解决方法,嗯,贴出来给大家看看:

function openReplacement(method,url,async,user,password) {
// some code

return open.apply(this,arguments);
}

function sendReplacement(data) {
// some code

if(this.onreadystatechange) this._onreadystatechange = this.onreadystatechange;
this.onreadystatechange = onReadyStateChangeReplacement;

return send.apply(this,arguments);
}

function onReadyStateChangeReplacement() {
// some code

if (this._onreadystatechange) return this._onreadystatechange.apply(this,arguments);
}

window.XMLHttpRequest.prototype.open = openReplacement;
window.XMLHttpRequest.prototype.send = sendReplacement;
})();

这个解决方案,无法监听全部的 XHR Events ,而且 readystatechange 事件是在调用 send 方法后才监听,也就无法监听到 readyState = 1 时的事件。同时,如果在使用 send 方法后再对 onreadystatechange 设置回调函数,会将 override 代码又一次 override,也就无法产生预想的效果

那如何才能正确地 override XHR 呢?贴上代码,一起来看看:

var oldXHR = window.XMLHttpRequest;

function newXHR() {
var realXHR = new oldXHR();

realXHR.addEventListener('abort',function () { ajaxEventTrigger.call(this,'ajaxAbort'); },false);

realXHR.addEventListener('error','ajaxError'); },false);

realXHR.addEventListener('load','ajaxLoad'); },false);

realXHR.addEventListener('loadstart','ajaxLoadStart'); },false);

realXHR.addEventListener('progress','ajaxProgress'); },false);

realXHR.addEventListener('timeout','ajaxTimeout'); },false);

realXHR.addEventListener('loadend','ajaxLoadEnd'); },false);

realXHR.addEventListener('readystatechange',function() { ajaxEventTrigger.call(this,'ajaxReadyStateChange'); },false);

return realXHR;
}

window.XMLHttpRequest = newXHR;
})();

这样,就为 XHR 添加自定义事件。如何调用

window.addEventListener('ajaxReadyStateChange',function (e) {
console.log(e.detail); // XMLHttpRequest Object
});
window.addEventListener('ajaxAbort',function (e) {
console.log(e.detail.responseText); // XHR 返回的内容
});

xhr.open('GET','info.json');
xhr.send();

需要注意的是,正常的 readystatechange 等事件 handler 返回的 eXMLHttpRequest 对象,但是自定义方法 ajaxReadyStateChange 等事件 handler 返回的 eCustomEvent 对象,而 e.detail 才是真正的 XMLHttpRequest 对象。而获得 Ajax 请求返回内容e.responseText 也需要修改e.detail.responseText

同时,addEventListener 方法必须挂载在 window 对象上,而不能是 XHR 实例上。

因为以上代码使用了 CustomEvent 构造函数,在现代浏览器上可以正常使用,但是在 IE 下,甚至连 IE 11 都不支持,所以需要加上 Polyfill,变成这样:

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;
})();
;(function () {
function ajaxEventTrigger(event) {
var ajaxEvent = new CustomEvent(event,false);

return realXHR;
}

window.XMLHttpRequest = newXHR;
})();

此时,就可以在 IE 9+、Chrome 15+、FireFox 11+、Edge、Safari 6.1+、Opera 12.1+ 上愉快地使用了,以上就是本文的全部内容,希望大家能够喜欢。

猜你在找的Ajax相关文章