我有一个相当标准化的揭示模块模式来创建用作实例的对象。有时,在这些模式中,在外部代码中不再使用或引用模块的情况下,需要取消超时或间隔。
此模式的简化示例:
function test() {
window.timer = maketimer();
}
function maketimer() {
var cls, my;
my = {
increment: 0,
timerid: null,
exec_timer: function() {
my.timerid = window.setInterval(my.time, 2000);
},
time: function() {
console.log("timer: ", my.timerid, my.increment++);
}
},
cls = {
//...
}
my.exec_timer();
return cls;
};
test();
// some time later...
test();
如果test
被调用两次,无论出于何种原因,变量window.timer
将替换为maketimer
的第二个实例,但第一个实例计时器将继续运行。
很多时候,我的模块本质上与DOM节点相关联,并且通常使用旧实例删除DOM节点,因此我理论上可以检查节点是否不存在或其位置在DOM之外,然后在这种情况下取消间隔。
然而,这更通用了,我希望能够处理DOM环境之外的超时。
答案 0 :(得分:1)
在这种情况下,我会将整个函数包装在包含instance
变量的IIFE中。在其中,您保存计时器。每次启动一个新的,旧的被摧毁:
(function(window) {
var timerInstance = null;
window.maketimer = function() {
var cls, my;
if(timerInstance) {
timerInstance.destroyInstance();
}
my = {
increment: 0,
timerid: null,
exec_timer: function() {
my.timerid = window.setInterval(my.time, 2000);
},
time: function() {
console.log("timer: ", my.timerid, my.increment++);
},
destroyInstance: function() {
window.clearInterval(my.timerid);
}
},
cls = {
//...
}
my.exec_timer();
timerInstance = my;
return cls;
}
})(window);
function test() {
window.timer = maketimer();
}
test();
test();
出于好奇,为什么你需要在全局变量上拥有实例? window.timer
非常通用,可以被其他脚本覆盖。
答案 1 :(得分:0)
试一试:更新下面的代码..
var settimer;
function test() {
clearTimeout(settimer);
settimer= setTimeout(function () {
window.timer = maketimer();
}, 100);
}
答案 2 :(得分:0)
扩展answer given by @nils,我创建了以下示例,用于构建一个模块,该模块接收单个DOM节点,并且只有在已经使用DOM节点时才清除先前的实例/计时器:
<div id="element1">[code here that may be updated with XHR]</div>
<div id="element2">[code here that may be updated with XHR]</div>
(function(window) {
var timerInstances = [];
window.maketimer = function(element) {
var cls, my, a;
// find instances where the passed element matches
for (a = 0; a < timerInstances.length; a += 1) {
if (timerInstances[a].element === element) {
console.log("instance already exists for element", element, "destroying...");
timerInstances[a].in.destroyInstance();
}
}
my = {
increment: 0,
timerid: null,
exec_timer: function() {
my.timerid = window.setInterval(my.time, 2000);
},
time: function() {
console.log("timer: ", my.timerid, my.increment++);
},
destroyInstance: function() {
window.clearInterval(my.timerid);
}
},
cls = {
//...
}
my.exec_timer();
timerInstances.push({
'element': element,
'in': my
});
return cls;
}
})(window);
function test(element) {
window.timer = maketimer(element);
}
test(document.getElementById("element1")); // produces 1 timer
test(document.getElementById("element1")); // cancels last, produces 1 timer
test(document.getElementById("element2")); // produces 1 timer
识别参数可以是这里的任何东西 - 在这种情况下它是一个DOM节点,但它可以很容易地是一个数字,字符串等。
如果您希望维护文档中一次只有一个实例的规则,则接受的答案非常有用,并且仍然是首选。