【问题标题】:XHR (Ajax) send prototype strange behaviourXHR (Ajax) 发送原型的奇怪行为
【发布时间】:2014-11-16 12:02:20
【问题描述】:

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

(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 并且我不想丢失那个回调。所以,我需要它,但那个回调永远不会被调用。

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

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

我需要此代码的网站正在使用 jQuery atm,但它也应该与原生 Javascript Ajax 一起使用。

【问题讨论】:

  • 更新了我的答案,在 FireFox 中犯了一个错误。您的代码中的错误无法在 FireFox 33.0 中重新生成,除非在没有打开页面的全新选项卡的控制台中运行它。我很好奇我的答案中的更新代码会在其他浏览器中为您生成什么(我只有 FireFox 和 Chrome)。

标签: javascript jquery ajax


【解决方案1】:

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 请求,但是您只能从您的代码中捕获打开和发送;不是来自第三方代码

[更新]

看来我搞错了。

在打开 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();

【讨论】:

    猜你喜欢
    • 2018-03-31
    • 2015-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多