如何修改另一个函数收到的 XMLHttpRequest 响应文本?

2024-01-02

我正在尝试修改我无法修改的函数收到的responseText。该函数创建了一个我可以附加到的 XMLHttpRequest,但我无法以允许我在原始函数接收之前修改内容的方式“包装”responseText。

这是完整的原始函数:

function Mj(a, b, c, d, e) {
    function k() {
        4 == (m && 'readyState' in m ? m.readyState : 0) && b && ff(b) (m)
    }
    var m = new XMLHttpRequest;
    'onloadend' in m ? m.addEventListener('loadend', k, !1)  : m.onreadystatechange = k;
    c = ('GET').toUpperCase();
    d = d || '';
    m.open(c, a, !0);
    m.send(d);
    return m
}
function ff(a) {
    return a && window ? function () {
        try {
            return a.apply(this, arguments)
        } catch(b) {
            throw jf(b),
                b;
        }
    } : a
}

我还尝试操纵接收函数 k();试图达到我的目标,但由于它不依赖于传递给函数的任何数据(例如 k(a.responseText);),所以我没有成功。

有什么办法可以实现这个目标吗?我不想使用 js 库(例如 jQuery);


EDIT:我知道我无法直接更改 .responseText,因为它是只读的,但我正在尝试找到一种方法来更改响应和接收函数之间的内容。


EDIT2:在下面添加了我尝试拦截和更改 .responseText 的方法之一,该方法已从此处进行了调整:猴子补丁 XMLHTTPRequest.onreadystatechange https://stackoverflow.com/questions/12575572/monkey-patch-xmlhttprequest-onreadystatechange

(function (open) {
XMLHttpRequest.prototype.open = function (method, url, async, user, pass) {
    if(/results/.test(url)) {
      console.log(this.onreadystatechange);
        this.addEventListener("readystatechange", function () {
            console.log('readystate: ' + this.readyState);
            if(this.responseText !== '') {
                this.responseText = this.responseText.split('&')[0];
            }
        }, false);
    }
    open.call(this, method, url, async, user, pass);
};
})(XMLHttpRequest.prototype.open);

EDIT3:我忘了指出函数 Mj 和 ff 不是全局可用的,它们都包含在匿名函数中 (function(){函数在这里})();


EDIT4:我更改了接受的答案,因为 AmmarCSE 不存在与 jfriend00 的答案相关的任何问题和复杂性。

简而言之,最佳答案如下:

监听您想要修改的任何请求(确保您的监听器将在原始函数目标之前拦截它,否则在使用响应后修改它是没有意义的)。

将原始响应(如果您想修改它)保存在临时变量中

将要修改的属性更改为“writable: true”,它将删除它所具有的任何值。就我而言,我使用

Object.defineProperty(event, 'responseText', {
    writable: true
});

Where event是监听返回的对象load or readystatechangexhr请求的事件

现在,您可以为响应设置任何您想要的内容,如果您想要的只是修改原始响应,那么您可以使用临时变量中的数据,然后将修改保存在响应中。


编辑:请参阅下面的第二个代码选项(它经过测试并且有效)。第一个有一些限制。


由于您无法修改任何这些函数,因此您似乎必须遵循 XMLHttpRequest 原型。这是一个想法(未经测试,但你可以看到方向):

(function() {
    var open = XMLHttpRequest.prototype.open;

    XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
        var oldReady;
        if (async) {   
            oldReady = this.onreadystatechange;
            // override onReadyStateChange
            this.onreadystatechange = function() {
                if (this.readyState == 4) {
                    // this.responseText is the ajax result
                    // create a dummay ajax object so we can modify responseText
                    var self = this;
                    var dummy = {};
                    ["statusText", "status", "readyState", "responseType"].forEach(function(item) {
                        dummy[item] = self[item];
                    });
                    dummy.responseText = '{"msg": "Hello"}';
                    return oldReady.call(dummy);
                } else {
                    // call original onreadystatechange handler
                    return oldReady.apply(this, arguments);
                }
            }
        } 
        // call original open method
        return open.apply(this, arguments);
    }

})();

这为 XMLHttpRequest 做了一个猴子补丁open()方法,然后当为异步请求调用该方法时,它会为 onReadyStateChange 处理程序执行猴子补丁,因为应该已经设置了该处理程序。然后,该修补函数可以在调用原始 onReadyStateChange 处理程序之前查看responseText,以便可以为其分配不同的值。

并且,最后因为.responseText是只读的,这会在调用之前替换一个虚拟的 XMLHttpResponse 对象onreadystatechange处理程序。这并非在所有情况下都有效,但如果 onreadystatechange 处理程序使用this.responseText得到回应。


并且,这里尝试将 XMLHttpRequest 对象重新定义为我们自己的代理对象。因为它是我们自己的代理对象,所以我们可以设置responseText财产为我们想要的任何东西。对于除onreadystatechange,该对象只是将 get、set 或函数调用转发给真正的 XMLHttpRequest 对象。

(function() {
    // create XMLHttpRequest proxy object
    var oldXMLHttpRequest = XMLHttpRequest;

    // define constructor for my proxy object
    XMLHttpRequest = function() {
        var actual = new oldXMLHttpRequest();
        var self = this;

        this.onreadystatechange = null;

        // this is the actual handler on the real XMLHttpRequest object
        actual.onreadystatechange = function() {
            if (this.readyState == 4) {
                // actual.responseText is the ajax result

                // add your own code here to read the real ajax result
                // from actual.responseText and then put whatever result you want
                // the caller to see in self.responseText
                // this next line of code is a dummy line to be replaced
                self.responseText = '{"msg": "Hello"}';
            }
            if (self.onreadystatechange) {
                return self.onreadystatechange();
            }
        };

        // add all proxy getters
        ["status", "statusText", "responseType", "response",
         "readyState", "responseXML", "upload"].forEach(function(item) {
            Object.defineProperty(self, item, {
                get: function() {return actual[item];}
            });
        });

        // add all proxy getters/setters
        ["ontimeout, timeout", "withCredentials", "onload", "onerror", "onprogress"].forEach(function(item) {
            Object.defineProperty(self, item, {
                get: function() {return actual[item];},
                set: function(val) {actual[item] = val;}
            });
        });

        // add all pure proxy pass-through methods
        ["addEventListener", "send", "open", "abort", "getAllResponseHeaders",
         "getResponseHeader", "overrideMimeType", "setRequestHeader"].forEach(function(item) {
            Object.defineProperty(self, item, {
                value: function() {return actual[item].apply(actual, arguments);}
            });
        });
    }
})();

工作演示:http://jsfiddle.net/jfriend00/jws6g691/ http://jsfiddle.net/jfriend00/jws6g691/

我在最新版本的 IE、Firefox 和 Chrome 中尝试过,它可以处理简单的 ajax 请求。

注意:我还没有研究过 Ajax 的所有高级方法(如二进制数据、上传等),以了解该代理是否足够彻底以完成所有这些工作(我猜可能还没有)无需进一步的工作,但它正在满足基本请求,因此看起来这个概念是有能力的)。


其他失败的尝试:

  1. 尝试从 XMLHttpRequest 对象派生,然后用我自己的构造函数替换构造函数,但这不起作用,因为真正的 XMLHttpRequest 函数不允许您将其作为函数调用来初始化我的派生对象。

  2. 尝试只是覆盖onreadystatechange处理程序和更改.responseText,但该字段是只读的,因此您无法更改它。

  3. 尝试创建一个虚拟对象作为this调用时的对象onreadystatechange,但是很多代码没有引用this,而是将实际对象保存在闭包中的局部变量中 - 从而击败了虚拟对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何修改另一个函数收到的 XMLHttpRequest 响应文本? 的相关文章

随机推荐