分享JavaScript监听全部Ajax请求事件的方法
2016-08-28 16:22
627 查看
若Ajax请求是由jQuery的
$.ajax发起的,默认情况下可以使用 jQuery的Global Ajax Event Handlers监听到Ajax事件,然而我遇到的却是用原生JavaScript发起的Ajax请求,所以这种方法行不通。
然后呢,还有其他方法,比如说 Pub/Sub,但是这个发起请求的 js 代码我是无法改动的,也就不存在向代码里添加 publish 的问题。同理,jQuery 的
.bind和
.trigger也无法使用。
最后,决定使用直接
overrideXMLHttpRequest,同时配合使用自定义事件。
在 StackOverflow 上搜索,发现有个歪果仁给出了一个不靠谱的解决方法,嗯,贴出来给大家看看:
;(function () { var open = window.XMLHttpRequest.prototype.open, send= window.XMLHttpRequest.prototype.send, onReadyStateChange; 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; })();
这个解决方案,无法监听全部的
XHREvents,而且
readystatechange事件是在调用
send方法后才监听,也就无法监听到
readyState = 1时的事件。同时,如果在使用
send方法后再对
onreadystatechange设置回调函数,会将
override的代码又一次
override,也就无法产生预想的效果。
那如何才能正确地 overrideXHR呢?贴上代码,一起来看看:
;(function() { function ajaxEventTrigger(event) { var ajaxEvent = new CustomEvent(event, { detail: this }); window.dispatchEvent(ajaxEvent); } var oldXHR= window.XMLHttpRequest; function newXHR() { var realXHR= new oldXHR(); 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; } window.XMLHttpRequest= newXHR; })();
这样,就为
XHR添加了自定义事件。如何调用?
var xhr = new XMLHttpRequest(); window.addEventListener('ajaxReadyStateChange', function (e) { console.log(e.detail); // XMLHttpRequestObject }); window.addEventListener('ajaxAbort', function (e) { console.log(e.detail.responseText); // XHR返回的内容 }); xhr.open('GET', 'info.json'); xhr.send();
需要注意的是,正常的
readystatechange等事件
handler返回的
e是
XMLHttpRequest对象,但是自定义方法
ajaxReadyStateChange等事件 handler返回的
e是
CustomEvent对象,而
e.detail才是真正的
XMLHttpRequest对象。而获得 Ajax 请求返回内容的
e.responseText也需要修改为
e.detail.responseText。
同时,
addEventListener方法必须挂载在
window 对象上,而不能是
XHR实例上。
因为以上代码使用了
CustomEvent构造函数,在现代浏览器上可以正常使用,但是在 IE 下,甚至连 IE 11 都不支持,所以需要加上
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; })(); ;(function () { function ajaxEventTrigger(event) { var ajaxEvent = new CustomEvent(event, { detail: this }); window.dispatchEvent(ajaxEvent); } var oldXHR= window.XMLHttpRequest; function newXHR() { var realXHR= new oldXHR(); 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; } window.XMLHttpRequest= newXHR; })();
此时,就可以在 IE 9+、Chrome 15+、FireFox 11+、Edge、Safari 6.1+、Opera 12.1+ 上愉快地使用了,以上就是本文的全部内容,希望大家能够喜欢。
您可能感兴趣的文章:
相关文章推荐
- 【JavaScript】AJAX之异步同步请求、FormData类型、事件监听接口
- JavaScript中绑定事件监听函数的通用方法[ addEvent() ]
- 转:JavaScript中绑定事件监听函数的通用方法
- 实例讲解使用原生JavaScript处理AJAX请求的方法
- 关于ajax请求后js绑定事件失效问题解决方法
- MVC设计模式 (1)、html页面事件触发ajax()方法调用ajax.js发送请求至请求目标文件
- javascript监听页面刷新和页面关闭事件方法详解
- JavaScript不同监听事件的方法
- javascript请求servlet实现ajax示例(分享)
- 用javascript监听页面上的所有ajax请求
- JavaScript监听文本框回车事件并过滤文本框空格的方法
- javascript 兼容W3c和IE的添加(取消)事件监听方法
- 全部对于Unity3D中 NGUI 触发事件的监听方法
- 添加/删除请求开始事件的方法 (asp.net ajax框架)
- JavaScript中绑定事件监听函数的通用方法[ addEvent() ]
- jQuery delegate方法实现Ajax请求绑定事件不丢失
- $.ajax的success函数中,监听【多张图片全部加载成功】事件
- JavaScript实现为事件句柄绑定监听函数的方法分析
- 页面操作全部采用调用函数方法实现(包括监听事件)