如何修补猴子修补XMLHTTPRequest
的{{1}}功能。我正在尝试添加一个函数,当从页面发出的每个ajax请求返回时,将调用该函数。
我知道这听起来像个糟糕的主意,但用例非常奇特。我想在控制台(jqconsole)中使用某个SDK,但在控制台内显示ajax调用的状态和结果,而不修改外部SDK。
我看过this post哪些信息非常好,但猴子修补回调似乎超出了我的JavaScript技能。
P.S不能使用jQuery,因为它只支持jQuery的jjj调用,而不是直接来自onreadystatechange
,这就是这里的情况。
答案 0 :(得分:9)
要修补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
处理程序。为简单起见,我没有包含other events的代码,例如onload
。另外,我没有考虑使用addEventListener
添加的事件。
以前的补丁适用于所有请求。但是,如果您只想将补丁限制为特定请求,该怎么办?具有特定URL或异步标志和特定请求正文的请求?
示例:拦截请求正文包含“TEST”的所有POST
个请求
(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);
};
我的示例非常基础,可以扩展以满足您的确切愿望。但是,这取决于你。
答案 1 :(得分:1)
你可以向中国人写的Ajax-hook学习!
启用Monkey补丁XMLHTTPRequest
是一个高级的js答案 2 :(得分:0)
假设您可以忽略IE ...
//Totally untested code, typed at the SO <textarea>... but the concept *should* work, let me know if it doesn't.
var OldXMLRequest = XMLHttpRequest;
// Create a new instance
function XMLHttpRequest() {
var ajax = new OldXMLRequest();
// save old function
var f = ajax.onreadystatechange;
ajax.onreadystatechange = function() {
console.log("Whatever!");
f(); // Call the old function
}
return ajax;
}