【Dmitri Pavlutin】用簡單的JavaScript的代碼捕獲XMLHttpRequest

譯者:道奇
做者:Dmitri Pavlutin
原文:Catch the XMLHttpRequest in Plain JavaScriptjavascript

當編寫Chrome擴展時,有時我須要捕獲JavaScript應用程序啓動和結束XMLHttpRequest (XHR)時的事件,可是由於注入到web頁面上下文的腳本不會修改原始的應用程序,這件事就很難作到,由於純XHR自己也不會觸發全局事件。html

有一些庫,如jQuery,確實觸發了全局事件ajaxStartajaxStop,甚至提供了全局ajax事件API。不幸的是,只有在使用庫方法進行AJAX調用時纔會觸發這些事件。因爲封裝的緣由,應用程序能夠抑制這些事件,設置全局選項爲false:java

$.ajax({
  url: "test.html",
  global: false
});
複製代碼

調查

JavaScript提供了對任何對象原型進行修改的方法,包括像XMLHttpRequest這樣的host對象,咱們能夠經過這些方法插入自定義行爲。open()send()將被包含自定義邏輯的新方法覆蓋,而後再調用原來的方法。web

讓咱們先確保XMLHttpRequest.prototype.openXMLHttpRequest.prototype.send是可寫的(writable):ajax

var openDescriptor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'open'),
 sendDescriptor = Object.getOwnPropertyDescriptor(XMLHttpRequest.prototype, 'send');

openDescriptor // prints {"writable": true, "configurable": true, ...}
sendDescriptor // prints {"writable": true, "configurable": true, ...}
複製代碼

Object.getOwnPropertyDescriptor()方法能夠獲得對象屬性的設置(描述),要重寫XMLHttpRequest對象的方法,須要將屬性的writable設置爲true:這樣咱們就能夠修改屬性了。bash

捕獲請求

使用如下代碼段來肯定XMLHttpRequest什麼時候開始和結束:app

var open = window.XMLHttpRequest.prototype.open,
  send = window.XMLHttpRequest.prototype.send;

function openReplacement(method, url, async, user, password) {
  this._url = url;
  return open.apply(this, arguments);
}

function sendReplacement(data) {
  if(this.onreadystatechange) {
    this._onreadystatechange = this.onreadystatechange;
  }
  /**
   * 當請求發出後,將你的代碼放在這裏  
   */
  this.onreadystatechange = onReadyStateChangeReplacement;
  return send.apply(this, arguments);
}

function onReadyStateChangeReplacement() {
  /**
   * 將readystatechange的代碼放在這裏
   */
  if(this._onreadystatechange) {
    return this._onreadystatechange.apply(this, arguments);
  }
}

window.XMLHttpRequest.prototype.open = openReplacement;
window.XMLHttpRequest.prototype.send = sendReplacement;
複製代碼

先把原始open()send()的引用保存下來,而後定義XMLHttpRequest的新方法:openReplacement()sendReplacement(),它們執行自定義代碼,再使用Function.apply()調用原始方法,最後,將新方法分配給XMLHttpRequest.prototype。由於修改了類原型,因此XMLHttpRequest的任何新實例都將使用自定義方法。 請注意,覆蓋的代碼段的應用應該在任何XHR請求啓動以前。async

例子

查看代碼示例,演示瞭如何捕獲發送和完成事件。ui

另請參閱 XMLHttpRequestthis

相關文章
相關標籤/搜索