0

TLDR我有一个在 openlayers 地图中的平底锅末端运行的功能。不希望它连续开火。


我有一个在平移地图结束时运行的函数。我希望它在平底锅完成后 3 秒后才会触发该功能。尽管我不想像 setTimeout 当前正在执行的那样将函数排队以触发 10 次左右。

如何将函数延迟运行 n 秒,然后无论调用多少次都只运行一次?

    map.events.register("moveend", map, function() {
      setTimeout(SetLocation, 5000);
    });

移动端:

moveend - triggered after a drag, pan, or zoom completes

上面的代码甚至使用了 setTimeout(func, delay); 运行时仍会触发多次。我怎样才能防止这种情况?


4

4 回答 4

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...

包装的函数将延迟指定的时间并且只执行一次。

于 2010-05-24T03:39:55.620 回答
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 :)
    ...
}
于 2010-05-24T04:07:05.567 回答
1

这正是 setTimeout 的用途。如果 setTimeout 调用该函数 10 次,则您的代码有问题,您没有发布。

还要记住 setTimeout 不会停止脚本。

于 2010-05-24T03:30:19.897 回答
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

于 2015-04-21T16:40:55.657 回答