对于monkey-patch XMLHttpRequest
,你需要知道一个AJAX请求一般是如何构造的:
- 构造函数调用
- 准备请求 (
setRequestHeader()
, open()
)
- 发送请求 (
.send
)。
通用补丁
(function(xhr) {
function banana(xhrInstance) { // Example
console.log('Monkey RS: ' + xhrInstance.readyState);
}
// Capture request before any network activity occurs:
var send = xhr.send;
xhr.send = function(data) {
var rsc = this.onreadystatechange;
if (rsc) {
// "onreadystatechange" exists. Monkey-patch it
this.onreadystatechange = function() {
banana(this);
return rsc.apply(this, arguments);
};
}
return send.apply(this, arguments);
};
})(XMLHttpRequest.prototype);
前面假设onreadystatechange
已分配给onreadystatechange
处理程序。为简单起见,我没有包含其他事件的代码,例如onload
. 此外,我没有考虑使用addEventListener
.
之前的补丁适用于所有请求。但是,如果您只想将补丁限制为特定请求怎么办?具有特定 URL 或异步标志和特定请求正文的请求?
有条件的猴子补丁
示例:拦截POST
请求正文中包含“TEST”的所有请求
(function(xhr) {
function banana(xhrInstance) { // Example
console.log('Monkey RS: ' + xhrInstance.readyState);
}
//
var open = xhr.open;
xhr.open = function(method, url, async) {
// Test if method is POST
if (/^POST$/i.test(method)) {
var send = this.send;
this.send = function(data) {
// Test if request body contains "TEST"
if (typeof data === 'string' && data.indexOf('TEST') >= 0) {
var rsc = this.onreadystatechange;
if (rsc) {
// Apply monkey-patch
this.onreadystatechange = function() {
banana(this);
return rsc.apply(this, arguments);
};
}
}
return send.apply(this, arguments);
};
}
return open.apply(this, arguments);
};
})(XMLHttpRequest.prototype);
使用的主要技术是使用透明重写...
var original = xhr.method;
xhr.method = function(){
/*...*/;
return original.apply(this, arguments);
};
我的示例非常基本,可以扩展以满足您的确切愿望。然而,这取决于你。