TLDR 我有一个在openlayers地图中的平移结束时运行的函数。不要让它不断发射。
我有一个在平移地图结束时运行的函数。 我想要它,以便在平底锅完成后3秒钟之前它不会触发该功能。虽然我不想将函数排队等待10次左右,就像setTimeout当前正在进行的那样。
如何将某个功能延迟运行n秒,然后只运行一次,无论它被调用多少次?
map.events.register("moveend", map, function() {
setTimeout(SetLocation, 5000);
});
Moveend:
moveend - triggered after a drag, pan, or zoom completes
上面的代码 甚至使用setTimeout(func,delay);它运行时仍会多次触发。我该如何防止这种情况?
答案 0 :(得分:3)
那么,满足您的要求,您可以构建一个简单的函数包装器:
var executeOnce = (function (fn, delay) {
var executed = false;
return function (/* args */) {
var args = arguments;
if (!executed) {
setTimeout(function () {
fn.apply(null, args); // preserve arguments
}, delay);
executed = true;
}
};
});
用法示例:
使用您的代码:
map.events.register("moveend", map, executeOnce(SetLocation, 5000));
其他用法:
var wrappedFn = executeOnce(function (a, b) {
alert(a + ' ' + b);
}, 3000);
wrappedFn('hello', 'world');
wrappedFn('foo', 'bar'); // this won't be executed...
包装函数将延迟指定的时间并仅执行一次。
答案 1 :(得分:2)
对于UI延迟,我建议将'clearTimeout'与'setTimeout'结合使用。对'setTimeout'的调用返回一个通常被忽略的ID。但是,如果您存储了ID,则下次打算调用'setTimeout'时,您可以取消之前的'setTimeout'(就好像您从未调用它一样)。
我认为你的情况是:
(mouse move triggers callback)
setTimeout (1st)
(mouse move triggers callback)
setTimeout (2nd)
...
callback from 1st setTimeout is called
callback from 2nd setTimeout is called
...
但是,如果你使用clearTimeout,你将拥有:
(mouse move triggers callback)
setTimeout (1st)
(mouse move triggers callback)
clearTimeout (1st)
setTimeout (2nd)
...
callback from last setTimeout is called
更新您提供的JavaScript代码:
var delayedSetLocationId = -1;
...
map.events.register("moveend", map, function() {
if (delayedSetLocationId >= 0) {
clearTimeout(delayedSetLocationId);
}
delayedSetLocationId = setTimeout(SetLocation, 5000);
});
...
function SetLocation(...) {
delayedSetLocationId = -1; // setTimeout fired, we can't cancel it now :)
...
}
答案 2 :(得分:1)
这正是setTimeout的用途。如果setTimeout正在调用该函数10次,那么你的代码就会出现问题,你没有发布。
另请注意,setTimeout不会暂停脚本。
答案 3 :(得分:0)
我实际上写了一篇关于此事的小帖子。它像CMS建议的那样糊涂。
代码段如下所示:
var delayonetimeaction = {
oneTimeActions: {},
/***
** Will wait the supplied "delay" until executing
** the supplied "action" (function).
** If called a second time before the with the
** same id, the first call will be ignored and
** instead the second will be used - that is the
** second action will be executed after the second
** supplied delay, not the first.
***/
bind: function (delay, id, action) {
// is there already a timer? clear if if there is
if (this.oneTimeActions[id]) clearTimeout(this.oneTimeActions[id]);
// set a new timer to execute delay milliseconds from last call
this.oneTimeActions[id] = setTimeout(function () {
action();
}, delay);
},
};
http://sds-digital.co.uk/post/2015/04/21/js-delayed-one-time-action.aspx