簡體   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