[英]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.