Попытка отследить количество невыполненных запросов AJAX в Firefox - PullRequest
6 голосов
/ 10 декабря 2010

Я использую Selenium для тестирования веб-приложения и не могу изменять код JavaScript приложения.Я пытаюсь отследить количество невыполненных запросов AJAX с помощью GreaseMonkey для переопределения XMLHttpRequest.send.Новый 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 завершает выполнение.

Ответы [ 2 ]

3 голосов
/ 10 декабря 2010

Я сам что-то сделал: http://jsfiddle.net/rudiedirkx/skp28agx/ (обновлено 22 января 2015 г.)

Скрипт (должен запускаться раньше всего):

(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. Что бы вы ни делали, как бы быстро и много вы ни щелкали по нему, через несколько секунд счетчик должен всегда заканчиваться на 0.

1 голос
/ 10 декабря 2010

Я использовал следующее:

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);
    };
}
...