对 Firefox browser.xul 的更改未实时更新

发布于 2024-11-09 05:41:48 字数 1419 浏览 0 评论 0原文

从 Firefox 扩展程序对 browser.xul 进行实时更改时,我遇到了某种事件循环问题。在我的代码完成之前,我对 browser.xul 所做的更改不会反映在浏览器窗口中。即使我使用 setTimeout 也会发生这种情况。

我有一个例子可以说明下面的问题。当我单击“xultest runtest”按钮时,几秒钟内没有任何反应,然后 xultest 文本显示为 XXXXXXXXXX。我从来没有看到过 XX,XXX,XXXX... 之间的东西。

有人可以解释 browser.xul 事件循环发生了什么以及如何解决它(谢谢!)?

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="css/overlay.css" type="text/css"?>
<overlay id="xultest-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <script type="text/javascript">
        <![CDATA[
        function xultestRunTest2() {
            for (var i = 0; i < 10; i++) {
                setTimeout(function() {
                        document.getElementById("xultest-text").value =
                            document.getElementById("xultest-text").value + "X" },
                    5000);
            }
        }
        ]]>
    </script>
    <toolbox id="navigator-toolbox">
        <toolbar id="xultest-toolbar" toolbarname="xultesttoolbar" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden">
            <toolbarbutton oncommand="xultestRunTest2();" label="xultest runtest" />
            <label id="xultest-text" class="toolbarbutton-text" value="X"></label>
        </toolbar>
    </toolbox>
</overlay>

I'm running into some sort of event loop issue when making real time changes to browser.xul from a Firefox extension. Changes I am making to the browser.xul are not reflected in the browser window until my code finishes. This happens even when I use setTimeout.

I have an example that demonstrates the issue below. When I click on the "xultest runtest" button nothing happens for a few seconds and then the xultest-text is shown as XXXXXXXXXX. I never see the XX,XXX,XXXX... in between.

Can someone explain what is going on with the browser.xul event loop and how to work around it (thanks!)?

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="css/overlay.css" type="text/css"?>
<overlay id="xultest-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <script type="text/javascript">
        <![CDATA[
        function xultestRunTest2() {
            for (var i = 0; i < 10; i++) {
                setTimeout(function() {
                        document.getElementById("xultest-text").value =
                            document.getElementById("xultest-text").value + "X" },
                    5000);
            }
        }
        ]]>
    </script>
    <toolbox id="navigator-toolbox">
        <toolbar id="xultest-toolbar" toolbarname="xultesttoolbar" class="chromeclass-toolbar" context="toolbar-context-menu" hidden="false" persist="hidden">
            <toolbarbutton oncommand="xultestRunTest2();" label="xultest runtest" />
            <label id="xultest-text" class="toolbarbutton-text" value="X"></label>
        </toolbar>
    </toolbox>
</overlay>

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

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

发布评论

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

评论(1

抚笙 2024-11-16 05:41:48

您这样做的方式是,在 for 循环内使用 setTimeout,您有效地做的是创建十个单独的超时,这些超时将大约同时触发,5单击按钮后几秒钟。

您需要做的是仅在前一个超时触发后创建每个新超时:

function xultestRunTest2(times) {
    if(times > 0){
        document.getElementById("xultest-text").value =
                        document.getElementById("xultest-text").value + "X";
        setTimeout(function(){ xultestRunTest2(times-1); }, 5000);
    }
}

...

<toolbarbutton oncommand="xultestRunTest2(10);" label="xultest runtest" />

或者(这是这三个方法中我最喜欢的方法):

function xultestRunTest2() {
    var times = 10;
    function do_cycle(){
        var el = document.getElementById("xultest-text");
        if(times > 0){
            el.value = el.value + "X";
            setTimeout(do_cycle, 5000);
            --times;
        }
    };
    do_cycle();
}

您也可以使用 setInterval() 代替:

function xultestRunTest2() {
    var times = 10,
        intervalId;
    intervalId = setInterval(function(){
        if(times > 0){
            document.getElementById("xultest-text").value =
                        document.getElementById("xultest-text").value + "X";
            --times;
        }
        else {
            clearInterval(intervalId);
            intervalId = null;
        }
    }, 5000);
}

The way you're doing it, with a setTimeout inside a for loop, what you effectively do is create ten separate timeouts that will all fire approximately at the same time, 5 seconds after you click the button.

What you need to do is create each new timeout only after the previous one fires:

function xultestRunTest2(times) {
    if(times > 0){
        document.getElementById("xultest-text").value =
                        document.getElementById("xultest-text").value + "X";
        setTimeout(function(){ xultestRunTest2(times-1); }, 5000);
    }
}

...

<toolbarbutton oncommand="xultestRunTest2(10);" label="xultest runtest" />

or (this is my favorite method of the three):

function xultestRunTest2() {
    var times = 10;
    function do_cycle(){
        var el = document.getElementById("xultest-text");
        if(times > 0){
            el.value = el.value + "X";
            setTimeout(do_cycle, 5000);
            --times;
        }
    };
    do_cycle();
}

You could also use setInterval() instead:

function xultestRunTest2() {
    var times = 10,
        intervalId;
    intervalId = setInterval(function(){
        if(times > 0){
            document.getElementById("xultest-text").value =
                        document.getElementById("xultest-text").value + "X";
            --times;
        }
        else {
            clearInterval(intervalId);
            intervalId = null;
        }
    }, 5000);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文