繁体   English   中英

如何在firefox插件中只运行一个代码实例?

[英]How to run only one instance of code in a firefox addon?

我在主窗口上监听onload事件,然后在每个浏览器/选项卡上监听DOMContentLoaded事件(我最多需要在浏览器中运行代码)并使用controlExecuted标记代码是在浏览器上运行的。

window.addEventListener("load", function(){
    try{
        var controlExecuted = 0;
        var appcontent = document.getElementById("appcontent"); // browser
        if (appcontent && controlExecuted == 0)
            appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
                appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
                alert('run code')
                controlExecuted = 1;
            }, true);
    }catch(e){
        // log!
    }
}, false);

这不起作用。 代码运行多次,具体取决于浏览器/选项卡的数量。

那么如何在firefox插件中只运行一个代码实例呢?

正如您所注意到的,每次打开新的浏览器窗口时,您的代码都会运行。 您可能没有意识到的是,一个窗口中的脚本完全独立于另一个窗口中的相同脚本。 也就是说,新的一组对象中的每个的时间,这意味着,实例化controlExecuted在一个窗口中是不一样的对象作为controlExecuted在另一个窗口。

在扩展程序中共享代码有两种方法:

  • 创建一个XPCOM组件 这是在浏览器扩展中共享代码的经典,更难(但非常强大)的方法。

  • 创建JavaScript代码模块 (JSM)。 简而言之:

    JavaScript代码模块是Gecko 1.9中引入的概念,可用于在不同的特权范围之间共享代码。 模块还可用于创建以前需要使用JavaScript XPCOM对象的全局JavaScript单例。

您还可以考虑将此标志设置为用户首选项 ,您的脚本的每个实例都可以读取该首选项 对于这样一个简单的用例,这可能是最简单的方法。

这里是使用JavaScript代码模块在firefox插件中仅运行一个代码实例的完整解决方案。

// modules/main.jsm
var EXPORTED_SYMBOLS = ["instancesControl"];

var instancesControl = {
    executed : 0,
    windowExecuting : 0,

    get : function(){
        return ++instancesControl.executed;
    },
    reset : function(){
        instancesControl.executed = 0;
    },
    getWindowExecuting : function(){
        return instancesControl.windowExecuting;
    },
    setWindowExecuting : function(id){
        instancesControl.windowExecuting = id;
    }   
};

主要调用代码:

 // load instancesControl module
Components.utils.import("resource://my-own-alias/main.jsm");

// identify window that will execute the one-instance code
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var windowID = util.outerWindowID;

// listen load window event 
window.addEventListener("load", function(){
    var appcontent = document.getElementById("appcontent");
    if (appcontent){
        // listen load content (on every tab)
        appcontent.addEventListener("DOMContentLoaded", function docLoader(e){
            appcontent.removeEventListener("DOMContentLoaded", docLoader, false);
            if (instancesControl.get() == 1){
                instancesControl.setWindowExecuting(windowID);

                // this code will run only once no matter
                // how many tabs or windows user opens.

            }
        }, true);
    }
}, false);

// re-init code if executing windows is closed
window.addEventListener("unload", function(){
    if (instancesControl.getWindowExecuting() == windowID){
        instancesControl.reset();
    }
}, false);

当然你可以改进它。 如果你这样做,请使用@nomikos进行评论。
谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM