发生什么事了?有一天还可以,第二天就“未定义”?

发布于 2024-11-06 01:58:54 字数 2878 浏览 5 评论 0原文

我正在写一个油脂猴脚本。最近我遇到了同样的问题两次,我不知道为什么会发生这种情况。

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。它工作正常,但整个功能尚未完成,我开始为我的脚本开发另一个功能。这些功能彼此没有联系。

几天后,我决定回到上面示例中的函数并完成它。我在没有修改任何内容的情况下对其进行了测试,并在 Firefox 的 (4) javascript 错误控制台中收到错误,指出 oPriority.chilNodes[cEntry] 未定义。注意,几天前我已经以完全相同的方式测试了它,根本没有这样的问题。

好的,所以,我决定将 oPriority 重命名为 oPriorityMass。神奇的是,问题解决了。

起初我想,也许两个对象存在一些冲突,在不同的函数中使用相同的名称,它们以某种方式继续存在,甚至超出了函数范围。我的脚本目前超过 6000 行,但我进行了搜索,发现除了在这个函数中之外,其他任何地方都没有提到 oPriority

有人可以告诉我,这是如何以及为什么会发生?我提到同样的事情现在发生了两次,它们发生在不同的函数中,但同样的问题 node.childNodes[c] is undefinednode 不为 null 并且 node .childNodes.length 显示正确的子节点数。 到底是怎么回事?我该如何避免此类问题?

谢谢

编辑:错误控制台给出的错误是 错误:未捕获的异常:TypeError:oPriorityMass.childNodes[cEntry]未定义

响应布罗克斯评论: GM_log(oPriorityMass.childNodes[cEntry]) 返回 undefined 作为消息。所以 node.childNodes[c] 通常是未定义的。

我的脚本创建一个 div 窗口。后来,上面的函数使用了这个div中的元素。元素确实有唯一的 ID,我 100% 确定原始站点不知道它们。 我的脚本有一个开始/停止按钮,可以在需要时运行一个或另一个功能。 我现在一直在刷新页面并运行我的脚本函数。我注意到有时(但并非总是)脚本会在第一次运行时失败并出现所描述的错误,但是,如果我再次运行它(不刷新页面),它就会开始工作。

该页面有一个 javascript 可以对其进行修改。它改变了一些元素的宽度,因此当浏览器调整大小时它也会改变。但我知道它对我的 div 没有影响,因为当我调整浏览器大小时它保持不变。

EDIT2

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

ns 函数只是在 ID 前面添加脚本名称。我在创建 HTML 元素时使用它,因此我的元素永远不会与网页具有相同的 id。所以 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 x 2 秒,即 10 秒。永远不会重试 5 次,可能会有所不同 一定还有其他事情发生?

I am writing a greasemonkey script. Recently i had this same problem twice and i have no idea why is this happening.

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

So the mystery of this is, one day i had oPriorityMass named as oPririoty. It was working fine, but the whole function was not yet complete and i started working on another functions for my script. These functions have no connection with each other.

Few days later i decided to go back to my function in the above example and finish it. I ran a test on it without modifying anything and got an error in the firefox's (4) javascript error console saying that oPriority.chilNodes[cEntry] is undefined. NOTE, few days back i have tested it exactly the same way and there was no such problem at all.

Ok, so, i decided to rename oPriority to oPriorityMass. Magically, problem got solved.

At first i thought, maybe there was some conflict of 2 objects, with the same name being used in different functions, which somehow continued to live even outside of function scope. My script is currently over 6000 lines big, but i did a search and found out that oPriority was not mentioned anywhere else but in this exact function.

Can somebody tell me, how and why is this happening? I mentioned same thing happened twice now and they happened in different functions, but the same problem node.childNodes[c] is undefined yet node is not null and node.childNodes.length show correct child count.
What is going on? How do i avoid such problems?

Thank you

EDIT: The error given by error console is
Error: uncaught exception: TypeError: oPriorityMass.childNodes[cEntry] is undefined

In response to Brocks comment:
GM_log(oPriorityMass.childNodes[cEntry]) returns undefined as a message. So node.childNodes[c] is the thing that is undefined in general.

My script creates a div window. Later, the above function uses elements in this div. Elements do have unique IDs and i am 100% sure the original site don't know about them.
My script has a start/stop button to run one or the other function when i need to.
I have been refreshing the page and running my script function now. I have noticed that sometimes (but not always) script will fail with the described error on the first run, however, if i run it again (without refreshing the page) it starts working.

The page has a javascript that modifies it. It changes some of it's element widths so it changes when the browser is resized. But i know it has no effect on my div as it is left unchanged when i resize browser.

EDIT2:

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

ns function just adds the script name in front of the ID. I use it when creating HTML element so my elements never have the same id as the web page. So bynID() is simple function that saves some typing time when i need to get element by ID.

I have modified my colli() function to include check

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

The loadPage function does 1 AJAX call, then i run few XPATH queries on it, but the actual contents are never appended/shown on the page, just kept inside document.createElement('div'), then this function calls colli(). So now, as i have modified my function, i checked the error console and saw that it may take up to 5 tries for it to start working correctly. 5 x 2seconds, thats 10 seconds. It is never 5 retries always, may vary There's got to be something else going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

诗化ㄋ丶相逢 2024-11-13 01:58:54

在 Firefox 中,childNode 可以包含 #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

任何适合且更易于维护的方法。

In Firefox, childNodes can include #text nodes. You should check to make sure that childNodes[cEntry] has nodeType == 1 or has a getAttribute method before trying to call it. e.g.

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

In the above in Firefox and similar browsers (i.e. based on Gecko and WebKit based browsers like Safari), d0 has one child node, a text node, and d1 has no child nodes.

So I would do something like:

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

Given that sCollNumber seems like it is a string integer (just guessing but it seems likely), you can also use:

Number(sCollNumber)

or

+sCollNumber

whichever suits and is more maintainable.

痴情 2024-11-13 01:58:54

那么,根据您上次的编辑,它现在可以工作,但有延迟,对吗?

但是当我建议延迟时,它并不意味着在等待时执行(甚至更多?)ajax 调用!

NOT

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

更像是:

setTimeout (colli, 2000);

所以ajax和loadPage所做的其他事情可以解释过度的延迟。

随机行为可能是由以下原因引起的:

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

如果存在任何框架或 iframe,并且您没有阻止对框架的操作,这将导致不稳定的行为。 (如果您确实阻止此类操作,则top是多余且不必要的。)
在这种情况下,GM 无法正确运行(具体取决于脚本的作用),通常看起来是从顶级作用域“切换”到框架作用域,反之亦然。

因此,最好将其更改为:

return document.getElementById (ns (sID) );

并确保您有:

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

作为代码的最上面几行。

除此之外,由于信息不足,几乎不可能发现问题。

要么将问题归结为一个完整独立配方来复制失败。

或者,发布或链接到完整未编辑脚本

So, according to your last edit, it now works, with the delay, right?

But when I suggested the delay it was not meant to do (even more?) ajax calls while waiting!!

NOT:

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

More like:

setTimeout (colli, 2000);

So the ajax and the other stuff that loadPage does could explain the excessive delay.

The random behavior could be caused by:

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

This will cause erratic behavior if any frames or iframes are present, and you do not block operation on frames. (If you do block such operation then top is redundant and unnecessary.)
GM does not operate correctly in such cases -- depending on what the script does -- often seeming to "switch" from top scope to frame scope or vice versa.

So, it's probably best to change that to:

return document.getElementById (ns (sID) );

And make sure you have:

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

as the top lines of code.

Beyond that, it's near impossible to see the problem, because of insufficient information.

Either boil the problem into a Complete, Self Contained, Recipe for duplicating the failure.

OR, post or link to the Complete, Unedited, Script.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文