XHR(Ajax)发送原型奇怪的行为

时间:2014-11-15 14:29:23

标签: javascript jquery ajax

我试图否决ajax方法的send方法。请参阅下面的代码:

(function() {
    var beforeCall = window.XMLHttpRequest.prototype.open,
        sendCall = window.XMLHttpRequest.prototype.send;

    window.XMLHttpRequest.prototype.open = function() {
        console.log("OPEN"); // Works

        // Only called once, but Ajax has 5 states, which are should log 5 times
        this.onreadystatechange = function(){ console.log("READYSTATE SOMETHING"); } 

        return beforeCall.apply(this, [].slice.call(arguments));
    };

    window.XMLHttpRequest.prototype.send = function() {
        var origCallback = this.onreadystatechange;
        this.onreadystatechange = function(){
            console.log("ONREADYSTATECHANGE"); // This log never gets called
            if( origCallback ) {
                origCallback.apply(this, [].slice.call(arguments))
            }
        };
        return sendCall.apply(this, [].slice.call(arguments));
    }
})();

记录OPEN,READYSTATE SOMETHING仅记录一次,但应记录每个状态吗?然后在我的发送功能上,我尝试再次覆盖它(应该在这里,因为也许我的网站已经有一个onreadystatechange而且我不想丢失那个回调。所以,我需要它,但是回调永远不会被调用。

原始功能仍适用于我上面的代码。但我没有得到我想要的额外日志。

任何人都知道为什么我的onreadystatechange与console.log("ONREADYSTATECHANGE")永远不会被调用?

我需要此代码的站点是使用jQuery atm,但它也应该使用本机Javascript Ajax。

1 个答案:

答案 0 :(得分:0)

似乎beforeCall.apply(this, [].slice.call(arguments));在FireFox中导致错误:

window.XMLHttpRequest.prototype.open = function() {
    console.log("OPEN"); // Works

    // Only called once, but Ajax has 5 states, which are should log 5 times
    this.onreadystatechange = function(){ console.log("READYSTATE SOMETHING"); } 
    console.log('still ok here');
    var ret = beforeCall.apply(this, [].slice.call(arguments));//error here
    console.log('this is not happening');
    return ret;//neither does this
};

适用于Chrome 32.0.1700.107

也许这是因为XMLHttpRequest是一个宿主对象,并且open函数的行为与普通JS函数的行为不同,可能following answer仍然相关。

这可能只是一个FireFox错误,但这意味着无法在任何XMLHttpRequest上监听任何打开和发送调用。您可以创建一个包装器并使用该包装器来调用XHR请求,但之后您只能捕获打开并从您的代码发送;不是来自第三方代码

<强> [UPDATE]

似乎我犯了一个错误。

当google.com打开时,在firebug控制台(FireFox 33)中运行以下代码对我来说很有用,但它在新的新标签中不起作用;必须访问一个网站。

(function() {
    var beforeCall = window.XMLHttpRequest.prototype.open,
        sendCall = window.XMLHttpRequest.prototype.send;

    window.XMLHttpRequest.prototype.open = function open() {
        var ret;
        console.log("OPEN");
        this.onreadystatechange = function(){ console.log("READYSTATE SOMETHING"); } 
        console.log('open still working');
        ret = beforeCall.apply(this, [].slice.call(arguments));
        console.log('open is done');
        return ret;
    };

    window.XMLHttpRequest.prototype.send = function send() {
        console.log('this is send');
        var origCallback = this.onreadystatechange,ret;
        this.onreadystatechange = function(){
            console.log("ONREADYSTATECHANGE");
            if( origCallback ) {
                origCallback.apply(this, [].slice.call(arguments))
            }
        };
        console.log('send still working');
        ret = sendCall.apply(this, [].slice.call(arguments));
        console.log('send done');
        return ret;
    }
})();

var xhr = new XMLHttpRequest();

xhr.open('GET','/');
//calling xhr.open with wrong order of parameters gives a not so elegant error
//xhr.open('/','GET')
xhr.send();