我使用Selenium测试Web应用程序,不允许修改应用程序的javascript代码。我试图通过使用GreaseMonkey来覆盖XMLHttpRequest.send来跟踪未完成的AJAX请求的数量。新的send()将基本上包装设置为onreadystatechange回调的内容,检查readyState,根据需要递增或递减计数器,并调用原始回调函数。
我遇到的问题似乎是一个特权问题,因为如果我只是浏览普通firefox浏览器中的页面,打开firebug并粘贴以下代码,它似乎工作正常:
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);
};
}
现在,如果我在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 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]
因此在尝试访问this.onreadystatechange
时似乎抛出了异常据推测,这是由于沙盒环境造成的。 任何帮助将不胜感激。我不依赖于这个解决方案,因此欢迎任何其他建议我做我需要的。只是我尝试了其他几个,这似乎是最有希望的。要求是我需要确保计数器在之后达到0 ,readyState变为4并且onreadystatechange回调已经完成执行。
答案 0 :(得分:3)
我自己做了一些事:http://jsfiddle.net/rudiedirkx/skp28agx/(2015年1月22日更新)
脚本(应先运行):
(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 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);
}
};
它会在每个动画帧(每秒约60次)中更新按钮中的计数器,与AJAX请求分开。无论你做什么,无论多快,多点击它,计数器应该总是在几秒后结束。
答案 1 :(得分:1)
我最终使用了以下内容:
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() {
unsafeWindow.XMLHttpRequest.prototype.oldsend.apply(this, arguments);
this.addEventListener('readystatechange', function() {
if (this.readyState == 2) {
/* LOADED */
unsafeWindow.document.ajax_outstanding++;
console.log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding);
} else if (this.readyState == 4) {
/* COMPLETED */
unsafeWindow.document.ajax_outstanding--;
console.log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding);
}
}, false);
};
}