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