Прерывистое поведение в моем сценарии AJAX, Greasemonkey - PullRequest
0 голосов
/ 26 октября 2011

У меня есть небольшой скрипт Greasemonkey, который не содержит случайную часть, но его результаты меняются с каждой перезагрузкой страницы.

Я нуб и, возможно, я делаю что-то не так, но я не знаю что.Я надеюсь, что вы сможете мне помочь.

Код слишком велик и слишком плохо написан, чтобы его можно было воспроизвести здесь, поэтому я постараюсь подвести итог моей ситуации:

  • У меня есть список ссылок, в которых href=javascript:void(0) и onclick=f(link_id).
  • f(x) делает XML-HTTP-запрос к серверу и возвращает адрес ссылки.
  • Мой сценарий предназначен для предварительного вычисления f(x) и изменения значения href при загрузке страницы.

У меня есть функция wait(), которая ожидает загрузки страницы, затемфункция findLinks(), которая получает узлы, которые должны быть изменены (с помощью xpath).
Затем функция sendRequest(), которая отправляет xhr на сервер.И, наконец, handleRequest(), который асинхронно (r.onreadystatechange) извлекает ответ и устанавливает ранее найденные узлы.

Видите ли вы что-то не так с этой идеей?

Используя сетевой анализатор, я вижу, что запрос всегда отправляется нормально, а также и ответ.

Иногда значение href изменяется, но иногда для некоторых ссылок это не так иостается javascript:void(0).

Я действительно не понимаю, почему это работает только половину времени ...

function getUrlParameterFromString(urlString, name) {
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var results = regex.exec(urlString);
    if (results == null) {
        return "";
    } else {
        return results[1];
    }
}

function getUrlParameter(name) {
    return getUrlParameterFromString(window.location.href, name);
}

function wait() {

    var findPattern = "//a";
    var resultLinks = document.evaluate(findPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    if (resultLinks == null || resultLinks.snapshotLength == 0) {
        return setTimeout(_wait, 100);

    } else {
        for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
            var node = resultLinks.snapshotItem(i);
            var s = node.getAttribute('onclick');
            var linkId = s.substring(2, s.length - 1); // f(x)->x
            sendRequest(linkId, node);
        }
    }
}

function sendRequest(linkId, nodeToModify) {

    window.XMLHttpRequest ? r = new XMLHttpRequest : window.ActiveXObject && (r = new ActiveXObject("Microsoft.XMLHTTP"));

    if (r) {
        r.open("POST", "some_url", !0);
        r.onreadystatechange = function () {
            handleRequest(nodeToModify, linkId, r);
        }
        r.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        r.send(linkId);
    }

}

function handleRequest(nodeToModify, num, r) {
 if (r.readyState == 4) {
     if (r.status == 200) {
         console.log('handleRequest() used');
         var a = r.responseText;
         if (a == null || a.length < 10) {
             sendRequest(num, nodeToModify);
         } else {
             var url = unescape((getUrlParameterFromString(a, "url")).replace(/\+/g, " "));
             nodeToModify.setAttribute('href', url);
             nodeToModify.setAttribute('onclick', "");
         }
     } else {
         alert("An error occurred: " + r.statusText)
     }
 }

}

wait();

1 Ответ

0 голосов
/ 26 октября 2011

Похоже, этот скрипт изменит ровно 1 ссылку.Поиск " замыкания "; этот цикл:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x
    sendRequest(linkId, node);
}

необходимо замыкание , чтобы sendRequest() получил правильные значения.В противном случае будет изменена только последняя ссылка.


Попробуйте:

for (var i = 0, len = resultLinks.snapshotLength; i < len; i++) {
    var node = resultLinks.snapshotItem(i);
    var s = node.getAttribute('onclick');
    var linkId = s.substring(2, s.length - 1); // f(x)->x

    //-- Create a closure so that sendRequest gets the correct values.
    ( function (linkId, node) {
            sendRequest (linkId, node);
        }
    )(linkId, node);
}
...