国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

分享JavaScript監聽全部Ajax請求事件的方法

2019-11-20 09:08:19
字體:
來源:轉載
供稿:網友

若Ajax請求是由jQuery的$.ajax發起的,默認情況下可以使用 jQuery的Global Ajax Event Handlers監聽到Ajax事件,然而我遇到的卻是用原生JavaScript發起的Ajax請求,所以這種方法行不通。

然后呢,還有其他方法,比如說 Pub/Sub,但是這個發起請求的 js 代碼我是無法改動的,也就不存在向代碼里添加 publish 的問題。同理,jQuery 的 .bind.trigger 也無法使用。

最后,決定使用直接 override XMLHttpRequest,同時配合使用自定義事件。 

在 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;})();

這個解決方案,無法監聽全部的 XHR Events ,而且 readystatechange 事件是在調用 send 方法后才監聽,也就無法監聽到 readyState = 1 時的事件。同時,如果在使用 send 方法后再對 onreadystatechange 設置回調函數,會將 override 的代碼又一次 override,也就無法產生預想的效果。

 那如何才能正確地 override XHR 呢?貼上代碼,一起來看看:

;(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); // 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 () { 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+ 上愉快地使用了,以上就是本文的全部內容,希望大家能夠喜歡。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 彭山县| 红原县| 德惠市| 柘城县| 洮南市| 兰西县| 永昌县| 上思县| 卢氏县| 中卫市| 庐江县| 泽州县| 和林格尔县| 汝州市| 昌宁县| 比如县| 武定县| 吴旗县| 灵川县| 巨野县| 新宾| 海丰县| 寻甸| 乌兰县| 阜阳市| 佛坪县| 正宁县| 顺义区| 扶余县| 依安县| 永修县| 红安县| 闵行区| 凉城县| 平乡县| 富源县| 苏尼特左旗| 深泽县| 常熟市| 甘南县| 鄂温|