猴子补丁XMLHTTPRequest.onreadystatechange

时间:2012-09-25 02:46:25

标签: javascript ajax xmlhttprequest monkeypatching

如何修补猴子修补XMLHTTPRequest的{​​{1}}功能。我正在尝试添加一个函数,当从页面发出的每个ajax请求返回时,将调用该函数。

我知道这听起来像个糟糕的主意,但用例非常奇特。我想在控制台(jqconsole)中使用某个SDK,但在控制台内显示ajax调用的状态和结果,而不修改外部SDK。

我看过this post哪些信息非常好,但猴子修补回调似乎超出了我的JavaScript技能。

P.S不能使用jQuery,因为它只支持jQuery的jjj调用,而不是直接来自onreadystatechange,这就是这里的情况。

3 个答案:

答案 0 :(得分:9)

要修补XMLHttpRequest,你需要知道如何构建一个AJAX请求:

  1. 构造函数调用
  2. 准备请求(setRequestHeader()open()
  3. 发送请求(.send)。
  4. 通用补丁

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