【问题标题】:Monkey patch XMLHTTPRequest.onreadystatechange猴子补丁 XMLHTTPRequest.onreadystatechange
【发布时间】:2012-09-16 12:50:25
【问题描述】:

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

我知道这听起来很糟糕,但用例却很奇特。我想将某个 SDK 与控制台 (jqconsole) 一起使用,但在控制台中显示 ajax 调用的状态和结果,而无需修改外部 SDK。

我查看了 this post,它提供了很好的信息,但没有关于猴子修补回调的内容,这似乎超出了我的 JavaScript 技能。

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

【问题讨论】:

    标签: javascript ajax xmlhttprequest monkeypatching


    【解决方案1】:

    假设你可以忽略 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;
    }
    

    【讨论】:

    • 1.在构造XHR 对象时,肯定没有readystatechange 事件处理程序。 2.使用f()调用方法时,上下文丢失:this应该是xhr实例,而不是windowundefined
    【解决方案2】:

    要猴子补丁XMLHttpRequests,你需要知道一个AJAX请求一般是如何构造的:

    1. 构造函数调用
    2. 准备请求(setRequestHeader()open()
    3. 发送请求 (.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);
    };
    

    我的示例非常基础,可以扩展以满足您的确切愿望。不过,这取决于您。

    【讨论】:

      【解决方案3】:

      你可以向中国人写的Ajax-hook学习!

      启用Monkey补丁XMLHTTPRequest的高级js

      【讨论】:

        猜你喜欢
        • 2016-09-01
        • 2012-12-18
        • 2020-01-09
        • 1970-01-01
        • 1970-01-01
        • 2010-09-29
        • 2021-04-04
        • 2011-04-15
        • 2017-05-20
        相关资源
        最近更新 更多