欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

分享JavaScript監(jiān)聽全部Ajax請(qǐng)求事件的方法

 更新時(shí)間:2016年08月28日 16:22:07   投稿:daisy  
最近在做一個(gè)小項(xiàng)目,引入了第三方j(luò)s文件,這個(gè)文件會(huì)調(diào)用XMLHttpRequest向服務(wù)器發(fā)送 Ajax請(qǐng)求,但是我有需要監(jiān)聽其Ajax請(qǐng)求的某些事件,以便額外地執(zhí)行其他腳本。于是稍微看了看監(jiān)聽 Ajax請(qǐng)求的事件方法,在這里分享給大家。有需要的朋友們可以參考借鑒。

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

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

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

在 StackOverflow 上搜索,發(fā)現(xiàn)有個(gè)歪果仁給出了一個(gè)不靠譜的解決方法,嗯,貼出來給大家看看:

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

這個(gè)解決方案,無法監(jiān)聽全部的 XHR Events ,而且 readystatechange 事件是在調(diào)用 send 方法后才監(jiān)聽,也就無法監(jiān)聽到 readyState = 1 時(shí)的事件。同時(shí),如果在使用 send 方法后再對(duì) onreadystatechange 設(shè)置回調(diào)函數(shù),會(huì)將 override 的代碼又一次 override,也就無法產(chǎn)生預(yù)想的效果。

 那如何才能正確地 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 添加了自定義事件。如何調(diào)用?

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 返回的內(nèi)容
});
 
xhr.open('GET', 'info.json');
xhr.send();

需要注意的是,正常的 readystatechange 等事件 handler 返回的 eXMLHttpRequest 對(duì)象,但是自定義方法 ajaxReadyStateChange 等事件 handler 返回的 eCustomEvent 對(duì)象,而 e.detail 才是真正的 XMLHttpRequest 對(duì)象。而獲得 Ajax 請(qǐng)求返回內(nèi)容的 e.responseText 也需要修改為 e.detail.responseText。

同時(shí),addEventListener 方法必須掛載在 window 對(duì)象上,而不能是 XHR 實(shí)例上。 

因?yàn)橐陨洗a使用了 CustomEvent 構(gòu)造函數(shù),在現(xiàn)代瀏覽器上可以正常使用,但是在 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;
})();

此時(shí),就可以在 IE 9+、Chrome 15+、FireFox 11+、Edge、Safari 6.1+、Opera 12.1+ 上愉快地使用了,以上就是本文的全部?jī)?nèi)容,希望大家能夠喜歡。

相關(guān)文章

最新評(píng)論