Что происходит? Однажды все в порядке, на следующий день - неопределенное? - PullRequest
1 голос
/ 08 мая 2011

Я пишу скрипт greasemonkey. Недавно у меня была одна и та же проблема дважды, и я понятия не имею, почему это происходит.

function colli(){
.....
var oPriorityMass = bynID('massadderPriority');//my own document.getElementById() function
var aPriorities = [];
if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}
.....
}

Итак, загадка в том, что однажды у меня было oPriorityMass, названное oPririoty. Он работал нормально, но вся функция еще не была завершена, и я начал работать над другими функциями для моего сценария. Эти функции не связаны друг с другом.

Несколько дней спустя я решил вернуться к своей функции в приведенном выше примере и закончить ее. Я запустил тест, ничего не меняя, и получил ошибку в консоли ошибок javascript в firefox (4), сообщающую, что oPriority.chilNodes[cEntry] is undefined. ПРИМЕЧАНИЕ: несколько дней назад я протестировал его точно так же, и такой проблемы не было вообще.

Хорошо, я решил переименовать oPriority в oPriorityMass. Волшебным образом проблема была решена.

Сначала я подумал, что, возможно, возник конфликт между двумя объектами с одним и тем же именем, используемыми в разных функциях, которые каким-то образом продолжали жить даже вне области действия функции. Мой скрипт в настоящее время имеет размер более 6000 строк, но я выполнил поиск и обнаружил, что oPriority не упоминается нигде, кроме этой точной функции.

Может кто-нибудь сказать мне, как и почему это происходит? Я уже упоминал, что одно и то же происходило дважды, и они выполнялись в разных функциях, но та же проблема node.childNodes[c] is undefined, но node не равна нулю, а node.childNodes.length показывает правильное количество детей. Что здесь происходит? Как мне избежать таких проблем?

Спасибо

РЕДАКТИРОВАТЬ: Ошибка консоли ошибки Error: uncaught exception: TypeError: oPriorityMass.childNodes[cEntry] is undefined

В ответ на комментарий Брокса: GM_log(oPriorityMass.childNodes[cEntry]) возвращает undefined как сообщение. Так что node.childNodes[c] - вещь, которая вообще не определена.

Мой скрипт создает окно div. Позже, вышеупомянутая функция использует элементы в этом div. Элементы имеют уникальные идентификаторы, и я на 100% уверен, что оригинальный сайт не знает о них. Мой скрипт имеет кнопку запуска / остановки для запуска той или иной функции, когда мне это нужно. Я обновлял страницу и теперь выполняю функцию скрипта. Я заметил, что иногда (но не всегда) скрипт завершается ошибкой с описанной ошибкой при первом запуске, однако, если я запускаю его снова (без обновления страницы), он начинает работать.

На странице есть javascript, который ее модифицирует. Он меняет ширину элемента, поэтому изменяется при изменении размера браузера. Но я знаю, что это не влияет на мой div, так как он остается неизменным при изменении размера браузера.

EDIT2 :

function bynID(sID) {
    return top.document.getElementById(ns(sID));
}
function ns(sText) {
    return g_sScriptName + '_' + sText;
}

ns функция просто добавляет имя скрипта перед идентификатором. Я использую его при создании элемента HTML, чтобы мои элементы никогда не имели такой же идентификатор, как веб-страница. Таким образом, bynID () - это простая функция, которая экономит время на ввод текста, когда мне нужно получить элемент по ID.

Я изменил свою функцию colli(), чтобы включить проверку

if (oPriorityMass) {
    if (!oPriorityMass.childNodes[0]) {
        GM_log('Retrying');
        setTimeout(loadPage,2000);
        return;
    }
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        var sCollNumber = oPriorityMass.childNodes[cEntry].getAttribute('coll');
        if (bynID('adder' + sCollNumber + '_check').checked)
            aPriorities.push(parseInt(sCollNumber));
    }
}

Функция loadPage выполняет 1 AJAX-вызов, затем я запускаю несколько запросов XPATH, но фактическое содержимое никогда не добавляется / не отображается на странице, просто сохраняется внутри document.createElement('div'), затем эта функция вызывает colli(). Итак, теперь, когда я изменил свою функцию, я проверил консоль ошибок и увидел, что для правильной работы может потребоваться до 5 попыток. 5 х 2 секунды, то есть 10 секунд. Никогда не бывает 5 попыток, может варьироваться. Должно быть что-то еще?

Ответы [ 2 ]

0 голосов
/ 10 мая 2011

Итак, согласно вашему последнему редактированию, теперь оно работает, с задержкой, верно?

Но когда я предложил задержку, она не должна была делать (даже больше?) Ajax-вызовов во время ожидания !!

НЕ

if (!oPriorityMass.childNodes[0]) {
    GM_log('Retrying');
    setTimeout(loadPage,2000);
    return;

Больше похоже на:

setTimeout (colli, 2000);

Таким образом, ajax и другие вещи, которые loadPage делает, могут объяснить чрезмерную задержку.


Случайное поведение может быть вызвано:

return top.document.getElementById(ns(sID));

Это приведет к ошибочному поведению, если присутствуют какие-либо кадры или iframe, и вы не блокируете работу с кадрами. (Если вы do блокируете такую ​​операцию, то top является избыточным и ненужным.)
GM не работает правильно в таких случаях - в зависимости от того, что делает скрипт - часто кажется, что он «переключается» из верхней области в область кадра или наоборот.

Так что, вероятно, лучше изменить это на:

return document.getElementById (ns (sID) );


И убедитесь, что у вас есть:

if (window.top != window.self)  //-- Don't run on frames or iframes
    return;

в качестве верхних строк кода.


Кроме того, почти невозможно увидеть проблему из-за недостатка информации.

Либо варить проблему в Complete , Автономный , Рецепт для дублирования ошибки.

ИЛИ, пост или ссылка на Завершено , Неотредактировано , Сценарий .

0 голосов
/ 08 мая 2011

В Firefox дочерние узлы могут включать узлы #text.Вы должны убедиться, что childNodes[cEntry] имеет nodeType == 1 или имеет getAttribute метод, прежде чем пытаться вызвать его.например,

<div id="d0">
</div>
<div id="d1"></div>

В приведенном выше описании в Firefox и аналогичных браузерах (т. е. на основе браузеров на основе Gecko и WebKit, таких как Safari), d0 имеет один дочерний узел, текстовый узел, а d1 не имеет дочерних узлов.

Итак, я бы сделал что-то вроде:

var sCollNumber, el0, el1;

if (oPriorityMass) {
    for (var cEntry=0; cEntry < oPriorityMass.childNodes.length; cEntry++) {
        el0 = oPriorityMass.childNodes[cEntry];

        // Make sure have an HTMLElement that will
        // have a getAttribute method
        if (el0.nodeType == 1) {
          sCollNumber = el0.getAttribute('coll');
          el1 = bynID('adder' + sCollNumber + '_check');

         // Make sure el1 is not falsey before attempting to
         // access properties
         if (el1 && el1.checked)

            // Never call parseInt on strings without a radix
            // Or use some other method to convert to Number
            aPriorities.push(parseInt(sCollNumber, 10));
    }
}

Учитывая, что sCollNumber выглядит как строковое целое число (просто догадывающееся, но кажется вероятным), вы также можете использовать:

Number(sCollNumber)

или

+sCollNumber

, в зависимости от того, что подходит и удобнее в обслуживании.

...