譯者:道奇
做者:Dmitri Pavlutin
原文:Catch the XMLHttpRequest in Plain JavaScriptjavascript
當編寫Chrome
擴展時,有時我須要捕獲JavaScript
應用程序啓動和結束XMLHttpRequest (XHR)
時的事件,可是由於注入到web
頁面上下文的腳本不會修改原始的應用程序,這件事就很難作到,由於純XHR自己也不會觸發全局事件。html
有一些庫,如jQuery
,確實觸發了全局事件ajaxStart
和ajaxStop
,甚至提供了全局ajax
事件API
。不幸的是,只有在使用庫方法進行AJAX
調用時纔會觸發這些事件。因爲封裝的緣由,應用程序能夠抑制這些事件,設置全局選項爲false
:java
$.ajax({
url: "test.html",
global: false
});
複製代碼
JavaScript
提供了對任何對象原型進行修改的方法,包括像XMLHttpRequest
這樣的host對象,咱們能夠經過這些方法插入自定義行爲。open()
和send()
將被包含自定義邏輯的新方法覆蓋,而後再調用原來的方法。web
讓咱們先確保XMLHttpRequest.prototype.open
和XMLHttpRequest.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