本文介绍了试图跟踪在Firefox中优秀的AJAX请求的数量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Selenium来测试一个Web应用程序,并且不允许修改应用程序的JavaScript代码。我试图通过使用GreaseMonkey来重写XMLHttpRequest.send跟踪未完成的AJAX请求的数量。新的send()将基本上包装onreadystatechange回调设置,检查readyState,递增或递减计数器,并调用原始的回调函数。

我遇到的问题似乎是一个特权问题,因为如果我只是浏览到一个普通的Firefox浏览器中的页面,打开萤火虫,并粘贴在下面的代码,它似乎工作正常:

  document.ajax_outstanding = 0; 
if(typeof XMLHttpRequest.prototype.oldsend!='function'){
XMLHttpRequest.prototype.oldsend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(){
console.log('in new send');
console.log('this.onreadystatechange ='+ this.onreadystatechange);
this.oldonreadystatechange = this.onreadystatechange;
this.onreadystatechange = function(){
if(this.readyState == 2){
/ * LOADED * /
document.ajax_outstanding ++;
console.log('set ajax_outstanding to'+ document.ajax_outstanding);

this.oldonreadystatechange.handleEvent.apply(this,arguments);
if(this.readyState == 4){
/ * COMPLETED * /
document.ajax_outstanding--;
console.log('set ajax_outstanding to'+ document.ajax_outstanding);
}
};
this.oldsend.apply(this,arguments);
};





$ b现在,如果我在GreaseMonkey用户中使用该片段的稍微修改版本这样的脚本:

  unsafeWindow.document.ajax_outstanding = 0; 
if(typeof unsafeWindow.XMLHttpRequest.prototype.oldsend!='function'){
unsafeWindow.XMLHttpRequest.prototype.oldsend = unsafeWindow.XMLHttpRequest.prototype.send;
unsafeWindow.XMLHttpRequest.prototype.send = function(){
GM_log('in new send');
GM_log('this.onreadystatechange ='+ this.onreadystatechange);
this.oldonreadystatechange = this.onreadystatechange;
this.onreadystatechange = function(){
if(this.readyState == 2){
/ * LOADED * /
unsafeWindow.document.ajax_outstanding ++;
GM_log('set ajax_outstanding to'+ unsafeWindow.document.ajax_outstanding);

this.oldonreadystatechange.handleEvent.apply(this,arguments);
if(this.readyState == 4){
/ * COMPLETED * /
unsafeWindow.document.ajax_outstanding--;
GM_log('set ajax_outstanding to'+ unsafeWindow.document.ajax_outstanding);
}
};
this.oldsend.apply(this,arguments);
};
}

然后我进入一个页面,做一些导致AJAX请求的事情,在javascript错误控制台中获取以下消息:

  http://www.blah.com/gmscripts/overrides:in new发送
未捕获的异常:[Exception ...Illegal valuensresult:0x80070057(NS_ERROR_ILLEGAL_VALUE)location:JS frame :: file:/// tmp / customProfileDir41e7266f56734c97a2ca02b1f7f528e1 / extensions /%7Be4a8a97b-f2ed-450b- b12d-ee​​082ba24781%7D / components / greasemonkey.js :: anonymous :: line 372data:no]





这可能是由于沙箱环境。
任何帮助将不胜感激。我不受这个解决方案的束缚,所以对于我所需要的任何其他建议都是值得欢迎的。这只是我尝试了其他几个人,这似乎是最有前途的。需要的是,我需要确保在readyState变为4之后计数器变为0,然后onreadystatechange回调完成执行。

解决方案

我自己做了一件事:(更新于2015年1月22日)
$ b 脚本(应该在其他任何地方运行):

 (function(xhr){
xhr.active = 0;
var pt = xhr.prototype;
var _send = pt.send ;
pt.send = function(){
xhr.active ++;
this.addEventListener('readystatechange',function(e){
if(this.readyState == 4 ){
setTimeout(function(){
xhr.active--;
},1);
}
});
_send.apply (this,arguments);
}
})(XMLHttpRequest);

和jsFiddle的测试脚本:

 window.onload = function(){
var btn = document.querySelector('button'),
active = btn.querySelector('span');

btn.onclick = function(){
// jQuery for ajax。 `delay`是一个jsFiddle参数
//保持一些请求活动更长时间。
jQuery.post('/ echo / json /',{
delay:Math.random()* 3,
});
};

updateActive();

function updateActive(){
active.textContent = XMLHttpRequest.active;
requestAnimationFrame(updateActive);
}
};

它更新每个动画帧的按钮中的计数器(〜每秒60次) AJAX请求。无论你做什么,无论多么快,你点击它,计数器应该总是在几秒钟后结束。0

I am using Selenium to test a web application and am not allowed to modify the application's javascript code. I am trying to track the number of outstanding AJAX requests by using GreaseMonkey to override XMLHttpRequest.send. The new send() will basically wrap what was set as the onreadystatechange callback, check the readyState, incrementing or decrementing the counter as appropriate, and calling the original callback function.

The problem that I'm having appears to be a privilege issue because if I just browse to a page in a normal firefox browser, open firebug and paste in the following code, it seems to work fine:

document.ajax_outstanding = 0;
if (typeof XMLHttpRequest.prototype.oldsend != 'function') {
    XMLHttpRequest.prototype.oldsend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function() {
        console.log('in new send');
        console.log('this.onreadystatechange = ' + this.onreadystatechange);
        this.oldonreadystatechange = this.onreadystatechange;
        this.onreadystatechange = function() {
            if (this.readyState == 2) {
                /* LOADED */
                document.ajax_outstanding++;
                console.log('set ajax_outstanding to ' + document.ajax_outstanding);
            }
            this.oldonreadystatechange.handleEvent.apply(this, arguments);
            if (this.readyState == 4) {
                /* COMPLETED */
                document.ajax_outstanding--;
                console.log('set ajax_outstanding to ' + document.ajax_outstanding);
            }
        };
        this.oldsend.apply(this, arguments);
    };
}

Now if I use a slightly modified version of that snippet from within a GreaseMonkey user script like so:

unsafeWindow.document.ajax_outstanding = 0;
if (typeof unsafeWindow.XMLHttpRequest.prototype.oldsend != 'function') {
    unsafeWindow.XMLHttpRequest.prototype.oldsend = unsafeWindow.XMLHttpRequest.prototype.send;
    unsafeWindow.XMLHttpRequest.prototype.send = function() {
        GM_log('in new send');
        GM_log('this.onreadystatechange = ' + this.onreadystatechange);
        this.oldonreadystatechange = this.onreadystatechange;
        this.onreadystatechange = function() {
            if (this.readyState == 2) {
                /* LOADED */
                unsafeWindow.document.ajax_outstanding++;
                GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding);
            }
            this.oldonreadystatechange.handleEvent.apply(this, arguments);
            if (this.readyState == 4) {
                /* COMPLETED */
                unsafeWindow.document.ajax_outstanding--;
                GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding);
            }
        };
        this.oldsend.apply(this, arguments);
    };
}

and I go to a page, do something that causes an AJAX request, I get the following message in the javascript error console:

http://www.blah.com/gmscripts/overrides: in new send
uncaught exception: [Exception... "Illegal value" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: file:///tmp/customProfileDir41e7266f56734c97a2ca02b1f7f528e1/extensions/%7Be4a8a97b-f2ed-450b-b12d-ee082ba24781%7D/components/greasemonkey.js :: anonymous :: line 372" data: no]

So it appears to be throwing the exception when trying to access this.onreadystatechange

Presumably, this is due to the sandboxed environment.Any help would be greatly appreciated. I am not tied to this solution, so any other suggestions for doing what I need are welcome. It's just that I've tried several others and this seems to be the most promising. The requirement is that I need to make sure that the counter gets to 0 after the readyState goes to 4 and the onreadystatechange callback has finished execution.

解决方案

I've made something myself: http://jsfiddle.net/rudiedirkx/skp28agx/ (updated 22 Jan 2015)

The script (should run before anything else):

(function(xhr) {
    xhr.active = 0;
    var pt = xhr.prototype;
    var _send = pt.send;
    pt.send = function() {
        xhr.active++;
        this.addEventListener('readystatechange', function(e) {
            if ( this.readyState == 4 ) {
                setTimeout(function() {
                    xhr.active--;
                }, 1);
            }
        });
        _send.apply(this, arguments);
    }
})(XMLHttpRequest);

And the jsFiddle's test script:

window.onload = function() {
    var btn = document.querySelector('button'),
        active = btn.querySelector('span');

    btn.onclick = function() {
        // jQuery for easy ajax. `delay` is a jsFiddle argument
        // to keep some requests active longer.
        jQuery.post('/echo/json/', {
            delay: Math.random() * 3,
        });
    };

    updateActive();

    function updateActive() {
        active.textContent = XMLHttpRequest.active;
        requestAnimationFrame(updateActive);
    }
};

It updates the counter in the button every animation frame (~ 60 times per second), separate from the AJAX requests. Whatever you do, however fast and much you click it, the counter should always end up at 0 after a few seconds.

这篇关于试图跟踪在Firefox中优秀的AJAX请求的数量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 17:31