Javascript 代码在控制台中工作,但加载时实际的用户脚本函数未定义

发布于 2024-12-16 20:22:37 字数 1504 浏览 2 评论 0原文

请记住,我不懂 JavaScript。我通过几个小时的阅读和到处提出的问题将这些内容放在一起。我不是程序员,只了解一点 HTML 和 CSS。

我正在尝试创建一个用户脚本,该脚本每隔一定时间单击页面上的指定按钮,直到满足特定条件,然后停止循环并按另一个按钮。感谢这里的一些帮助,我得到了一段代码,当粘贴到 Chrome 或 Firebug 控制台时,它完全按照我想要的方式执行。

但是,如果我将此脚本安装为 Chrome 扩展程序或 Greasemonkey 脚本,则会收到未定义的错误。

var int = self.setInterval ("refresh ()", 4000);

function stop () { 
    // Stop the loop before joining server
    int = window.clearInterval (int)
}

function join () { 
    // Click Join Server button
    document.getElementsByClassName (
        "base-button-arrow-almost-gigantic"
    )[0].click ();
}

function refresh () { 
    // If current players < max, cancel loop and join server
    var playersElement = document.getElementById ('server-info-players');
    var players = playersElement.textContent;
    var parts = players.split ("/");

    var current = parseFloat (parts[0]);
    var max = parseFloat (parts[1]);

    if (current < max) {
        stop ()
        join ()
    }

    var refreshBtn = document.querySelector (
        "div.serverguide-header-refresh-button div[type='reset'] a"
    );
    var clickEvent = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    refreshBtn.dispatchEvent (clickEvent);
}

如果将其直接粘贴到控制台中,它将按预期工作,点击刷新按钮直到满足条件,然后按加入按钮。作为用户脚本安装时,我从 Chrome 和 Firebug 中收到以下错误:

Uncaught ReferenceError: refresh is not defined
(anonymous function)

这只是以四秒的间隔返回。

关于用户脚本有什么我不知道的吗?我做错了什么?

Please keep in mind that I don't know javascript. I've put this together from hours of reading and a question here and there. I'm not a programmer and only know a bit of HTML and CSS.

I'm trying to create a userscript that clicks a specified button on a page at intervals until a certain condition is met, then stop the loop and press another button. Thanks to some help here I got a chunk of code that does exactly what I want it to do when pasted into the Chrome or Firebug console.

However, if I install this script as a Chrome extension or Greasemonkey script, I get undefined errors.

var int = self.setInterval ("refresh ()", 4000);

function stop () { 
    // Stop the loop before joining server
    int = window.clearInterval (int)
}

function join () { 
    // Click Join Server button
    document.getElementsByClassName (
        "base-button-arrow-almost-gigantic"
    )[0].click ();
}

function refresh () { 
    // If current players < max, cancel loop and join server
    var playersElement = document.getElementById ('server-info-players');
    var players = playersElement.textContent;
    var parts = players.split ("/");

    var current = parseFloat (parts[0]);
    var max = parseFloat (parts[1]);

    if (current < max) {
        stop ()
        join ()
    }

    var refreshBtn = document.querySelector (
        "div.serverguide-header-refresh-button div[type='reset'] a"
    );
    var clickEvent = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    refreshBtn.dispatchEvent (clickEvent);
}

If this is pasted directly into the console it works as intended, hitting the refresh button until the condition is met then pressing the Join button. Installed as a userscript I get the follow error from both Chrome and Firebug:

Uncaught ReferenceError: refresh is not defined
(anonymous function)

This just keep being returned on four second intervals.

Is there something about userscripts that I don't know? What am I doing wrong?

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

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

发布评论

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

评论(2

何时共饮酒 2024-12-23 20:22:37

注意:

  1. 如果代码经过缩进和格式化以便于阅读,人们更有可能阅读您的代码。 ;-)  请参阅我对您的问题所做的编辑,并且有很多有助于格式化的工具

  2. 回复:setInterval("refresh()"...; 不要使用这样的引用代码调用 setInterval (和类似的函数)。它总是很糟糕的形式(不必要地使用eval())并且它完全由于沙箱的原因,在 Greasemonkey 中不起作用

  3. 同样,有时在定义之前使用的 JS 将是“未定义”——尤其是在 eval 情况下。

  4. 不要使用不明确的、常见的或保留字作为变量或函数名称。 int 尤其糟糕,因为大多数人会将其读作“整数”,并且它是几乎所有主流语言中的保留词。

  5. 要小心 selfwindow 对象。它们在 Greasemonkey 上下文中具有不同的含义/行为。

  6. 分号在 javascript 中并不总是必需的,确实如此,但要养成始终使用它们的习惯。它会为你减轻将来的痛苦,并使代码更容易理解。

无论如何,如果代码可以在控制台中运行,那么这也应该可以在脚本中运行:

var refreshInterval;

function stopRefreshTimer () { 
    // Stop the loop before joining server
    clearInterval (refreshInterval);
}

function joinServer () { 
    // Click Join Server button
    document.getElementsByClassName (
        "base-button-arrow-almost-gigantic"
    )[0].click ();
}

function refreshUntilJoiningServer () { 
    // If current players < max, cancel loop and join server
    var playersElement  = document.getElementById ('server-info-players');
    var players         = playersElement.textContent;
    var parts           = players.split ("/");

    var current         = parseFloat (parts[0]);
    var max             = parseFloat (parts[1]);

    if (current < max) {
        stopRefreshTimer ();
        joinServer ();
    }

    var refreshBtn      = document.querySelector (
        "div.serverguide-header-refresh-button div[type='reset'] a"
    );
    var clickEvent      = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    refreshBtn.dispatchEvent (clickEvent);
}

refreshInterval         = setInterval (refreshUntilJoiningServer, 4000);

Notes:

  1. People are more likely read your code if it's indented and formatted for legibility. ;-)   See the edit I made to your question, and there are plenty of tools that help with formatting.

  2. Re: setInterval("refresh()"...; do not call setInterval (and similar functions) with quoted code like that. It's always poor form (uses eval() unnecessarily) and it flat-out won't work in Greasemonkey due to the sandbox.

  3. Likewise, sometimes JS that is used before it is defined will be "not defined" -- especially in eval situations.

  4. Do not use ambiguous, common, or reserved words as variable or function names. int is especially bad as most will read it as "Integer" and it is a reserved word in almost every mainstream language.

  5. Be careful with the self and window objects. These have different meanings/behaviors in a Greasemonkey context.

  6. Semicolons are not always required in javascript, true, but get into the habit of always using them. It will save you grief in the future and makes the code slightly easier to understand.

Anyway, if the code worked from the console, then this should also work from a script:

var refreshInterval;

function stopRefreshTimer () { 
    // Stop the loop before joining server
    clearInterval (refreshInterval);
}

function joinServer () { 
    // Click Join Server button
    document.getElementsByClassName (
        "base-button-arrow-almost-gigantic"
    )[0].click ();
}

function refreshUntilJoiningServer () { 
    // If current players < max, cancel loop and join server
    var playersElement  = document.getElementById ('server-info-players');
    var players         = playersElement.textContent;
    var parts           = players.split ("/");

    var current         = parseFloat (parts[0]);
    var max             = parseFloat (parts[1]);

    if (current < max) {
        stopRefreshTimer ();
        joinServer ();
    }

    var refreshBtn      = document.querySelector (
        "div.serverguide-header-refresh-button div[type='reset'] a"
    );
    var clickEvent      = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    refreshBtn.dispatchEvent (clickEvent);
}

refreshInterval         = setInterval (refreshUntilJoiningServer, 4000);
一笔一画续写前缘 2024-12-23 20:22:37

简而言之,无论是 setInterval 还是事件处理程序,该调用都是在 Greasemonkey 沙箱消失后发生的。

页面加载 -> Greasemonkey 启动,运行脚本,然后 Greasemonkey 消失。 (4 秒过去)你的脚本现在开始执行。

您需要做的是将范围与 setInterval 一起传递,因此当这 4 秒过去时它仍然存在。您可以使用匿名函数轻松完成此操作。 (同时,避免您当前正在执行的隐含 eval()...)

粗略地说,您的代码最终应该如下所示:

var notInt = self.setInterval(function () {

    function stopRefreshTimer() {
        // Stop the loop before joining server
        clearInterval(refreshInterval);
    }

    function joinServer() {
        // Click Join Server button
        document.getElementsByClassName("base-button-arrow-almost-gigantic")[0].click();
    }

    // If current players < max, cancel loop and join server
    var playersElement = document.getElementById('server-info-players');
    var players = playersElement.textContent;
    var parts = players.split("/");

    var current = parseFloat(parts[0]);
    var max = parseFloat(parts[1]);

    if (current < max) {
        stopRefreshTimer();
        joinServer();
    }

    var refreshBtn = document.querySelector("div.serverguide-header-refresh-button div[type='reset'] a");
    var clickEvent = document.createEvent('MouseEvents');
    clickEvent.initEvent('click', true, true);
    refreshBtn.dispatchEvent(clickEvent);
}, 4000);

Both with setInterval and the event handler, in a nutshell, that call is happening after the Greasemonkey sandbox has gone away.

Page loads -> Greasemonkey kicks in, runs script, Greasemonkey goes away. (4 seconds pass) Your script now happens.

What you need to do is pass the scope along with the setInterval, so it's still there when those 4 seconds have passed. You can easily do it with an anonymous function. (And at the same time, avoid the implied eval() that you're doing currently...)

Roughly, this is what your code should end up looking like:

var notInt = self.setInterval(function () {

    function stopRefreshTimer() {
        // Stop the loop before joining server
        clearInterval(refreshInterval);
    }

    function joinServer() {
        // Click Join Server button
        document.getElementsByClassName("base-button-arrow-almost-gigantic")[0].click();
    }

    // If current players < max, cancel loop and join server
    var playersElement = document.getElementById('server-info-players');
    var players = playersElement.textContent;
    var parts = players.split("/");

    var current = parseFloat(parts[0]);
    var max = parseFloat(parts[1]);

    if (current < max) {
        stopRefreshTimer();
        joinServer();
    }

    var refreshBtn = document.querySelector("div.serverguide-header-refresh-button div[type='reset'] a");
    var clickEvent = document.createEvent('MouseEvents');
    clickEvent.initEvent('click', true, true);
    refreshBtn.dispatchEvent(clickEvent);
}, 4000);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文