国产探花免费观看_亚洲丰满少妇自慰呻吟_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+ 上愉快地使用了,以上就是本文的全部內容,希望大家能夠喜歡。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 蒙自县| 宜兰市| 九龙城区| 德州市| 洪雅县| 文安县| 淮南市| 沁水县| 临邑县| 商洛市| 铁岭县| 麟游县| 巨鹿县| 柳河县| 汝阳县| 扎赉特旗| 上林县| 从化市| 祁连县| 五华县| 海盐县| 阿鲁科尔沁旗| 香港 | 峡江县| 吉安市| 和林格尔县| 三江| 钦州市| 晋城| 渭源县| 齐齐哈尔市| 华亭县| 锦州市| 石台县| 金乡县| 平和县| 毕节市| 富锦市| 措勤县| 和政县| 峨边|