如何在窗口调整大小事件期间仅调用一次javascript函数?

发布于 2024-09-08 11:15:33 字数 461 浏览 5 评论 0原文

在 jQuery 调整事件页面大小 上,据说:

“调整大小处理程序中的代码不应该 依赖于次数 调用处理程序。根据 实现,调整大小事件可以是 调整大小时连续发送 正在进行中(典型行为 基于 Internet Explorer 和 WebKit Safari 和 Chrome 等浏览器), 或者仅在调整大小结束时一次 操作(典型行为 火狐)。”

我观察到应用程序中的内存泄漏不断增加,因为我不断调整浏览器窗口的大小,这反过来又不断触发特定的代码。我认为调整大小事件在调整大小操作结束时仅调用一次,但是现在读完这篇文章后,我认为我的代码简直是矫枉过正,

是否有任何既定的做法可以在调整大小操作已经结束时仅触发一次跨浏览器回调?

On jQuery resize event page it is said that:

"Code in a resize handler should never
rely on the number of times the
handler is called. Depending on
implementation, resize events can be
sent continuously as the resizing is
in progress (the typical behavior in
Internet Explorer and WebKit-based
browsers such as Safari and Chrome),
or only once at the end of the resize
operation (the typical behavior in
Firefox)."

Right now I observe increasing memory leak in my app, as I'm continuously resizing browser window, which in it's turn continuously triggers specific code. I thought resize event is called only once in the end of the resize operation, but now after reading this I think my code is simply overkilling itself.

Is there any established practice to trigger a callback cross-browser only once, when resize operation has already ended?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

超可爱的懒熊 2024-09-15 11:15:33

由于您无论如何都在使用 jQuery,请查看 Ben Alman 的 doTimeout 插件。您可以使用它来反跳您的事件处理程序。

甚至还有一个 与您的情况完全匹配的示例

$(window).resize(function(){
  $.doTimeout( 'resize', 250, function(){
    // do something computationally expensive
  });
});

关键在这里也就是说,只有在接下来的 250 毫秒内未再次调用调整大小处理程序(即未触发调整大小事件)时,才会执行传递给 doTimeout 的函数。如果是这样,计时器将中止并启动新的计时器。

As you are using jQuery anyway, have a look at Ben Alman's doTimeout plugin. You can use it to debounce your event handler.

There is even an example that matches exactly your case:

$(window).resize(function(){
  $.doTimeout( 'resize', 250, function(){
    // do something computationally expensive
  });
});

The key here is that, the function passed to doTimeout is only executed if the resize handler is not called (i.e. the resize event is not fired) again during the next 250 ms. If so, the timer is aborted and a new one is started.

≈。彩虹 2024-09-15 11:15:33

所以我认为这个答案最好通过执行以下操作而不是 $.doTimeout 方法(它似乎不想在另一个 JQuery 语句内运行)来实现:

// create a global timer var:
var _timeVar;

// create your jQuery window resize method. The clearTimeout() method prevents the
$(window).resize(function(){
    clearTimeout( _timerVar );
    _timerVar = setTimeout('resizeUI()', 250);
});

// my resize function
function resizeUI() {
    // resize stuff here
}

So this answer I think is best served by doing the following instead of the $.doTimeout method (which seems to not want to run inside of another JQuery statement:

// create a global timer var:
var _timeVar;

// create your jQuery window resize method. The clearTimeout() method prevents the
$(window).resize(function(){
    clearTimeout( _timerVar );
    _timerVar = setTimeout('resizeUI()', 250);
});

// my resize function
function resizeUI() {
    // resize stuff here
}
九命猫 2024-09-15 11:15:33

我认为如果您向我们展示您的调整大小事件处理程序将会有所帮助。

在没有看到您的代码的情况下,我所能建议的就是采用某种限制来限制每秒可以触发处理程序的次数:

var lastTime = 0;
$(window).resize(function(){
    // This condition will only be met (at most) once every second
    if (lastTime + 1000 < +new Date) {
        // do your stuff...
        lastTime = +new Date;
    }
});

I think it would help if you showed us your resize event handler.

Without seeing your code all I can suggest is to have some kind of thottle to limit how many times the handler can be triggered per second:

var lastTime = 0;
$(window).resize(function(){
    // This condition will only be met (at most) once every second
    if (lastTime + 1000 < +new Date) {
        // do your stuff...
        lastTime = +new Date;
    }
});
热血少△年 2024-09-15 11:15:33

你可以使用一个标志。在函数开始时设置标志 - 如果在调整大小完成后取消设置。然后不允许再次调用该函数,除非该标志已重置。

You could use a flag. Set the flag at the start of the function - unset if after the resize in complete. Then do not allow the function to be called again unless the flag has been reset.

友谊不毕业 2024-09-15 11:15:33

感谢您的提示,但我认为它不适用于像 IE 或 Webkit 这样在调整大小时连续触发事件的浏览器。
原因如下:
假设窗口几秒钟没有调整大小,然后调整它的大小:
在第一个事件触发时,lastTime 变量将小于 new Date,因此将执行调整大小的代码。
由于其他事件在调整大小时以高速率触发,因此它们都将不到一秒并且不会触发。最终结果是,对于我们试图捕获的最终窗口大小,不会发生调整大小。

如果我误解了您的代码,请现在告诉我,因为我正在寻找解决方案,并且我希望避免像其他建议的解决方案那样涉及太多计时器。

谢谢。

Thanks for the tip but I don't think it would work on a browser like IE or Webkit that fire events continuously while resizing.
Here is why :
Let say that the window has not been resized for several seconds and then you resize it :
At the first event fired the lastTime var will be smaller than new Date so the code for resizing will e executed.
As the other events are fired at high rate while resizing they will all fall short of one second and will not fire.End result is that the resize will not happen for the final window size which is the one we are trying to capture.

Please let me now if I misunderstood your code, because I am looking for a solution for this and I'd like to avoid having too many timers involved as in other solutions proposed.

Thanks.

失与倦" 2024-09-15 11:15:33

当 Firefox 启动时(在 XUL Addon 中工作),我接到多个电话。如果您只想一次调用代码一次(当代码已经运行时再次调用代码时会导致错误),您可以仅使用触发器(标志[布尔值])。

MyClass = {
  is_resizing: false,
  // another variables here...

  resized: function() {
    if (! MyClass.is_resizing) {
      // your code goes here...
    }
  },

  // another methods here...
};

window.addEvenetListener('resize', function(e) { MyClass.resized(); e.stopPropagation(); }, false);

I got multiple calls when Firefox is starting (working in XUL Addon). If you want to call your code just ONCE in a time (errors caused when code called over again while your code is already running) you can use just a trigger (flag [boolean value]).

MyClass = {
  is_resizing: false,
  // another variables here...

  resized: function() {
    if (! MyClass.is_resizing) {
      // your code goes here...
    }
  },

  // another methods here...
};

window.addEvenetListener('resize', function(e) { MyClass.resized(); e.stopPropagation(); }, false);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文