【问题标题】:Javascript event execution deferred in a queueJavascript 事件执行延迟在队列中
【发布时间】:2023-03-05 15:10:01
【问题描述】:

我正在尝试解释我的问题,以了解解决问题的更好方法。我搜索了一下,但我不知道如何准确搜索:

  • 我有一个包含三个区域的 HTML 页面:面板 A、网格 B 和网格 C。
  • 在网格 C 上,我可以对一行执行操作(仅单击它),以更新面板 A 和网格 B 上的一些计数器,但它们是根据数据库总数计算的。
  • 当我执行行操作时,我会立即更新行并触发面板 A 和网格 B 监听的事件,该事件向服务器发送两个请求以更新其计数器。

每行更新都有点繁重,如果用户快速点击不同的行,javascript 执行会被锁定,面板 A 和网格 B 的更新会淹没服务器,如果在 1 或 2 秒内可能会延迟执行一次事件未触发。

我会解决 listenTo 回调的问题,因为它可能是另一个面板,必须“立即”执行事件操作。

我想象这样的事情(仅在没有监听事件 2 秒后刷新),但我认为必须有更好的方法:

var eventTimeout = {}; // one for listener
element.bind('eventName' function() {
    if (eventTimeout['eventName']) {
        clearTimeout(eventTimeout['eventName']); // I understand that if the timeout has been exhausted no error is thrown
    }
    eventTimeout['eventName'] = 
        setTimeout(function() {
            eventTimeout['eventName'] = null;
            doAction(); 
        }, 2000);
});

我将离开那个实现(我还没有测试过),当我有更多时间时,我会把它放在一个 JSFiddle 上以帮助理解。

【问题讨论】:

    标签: javascript jquery events


    【解决方案1】:

    您的代码走在了正确的轨道上,但您可能希望使用类似 lodash-throttle 的函数装饰器,而不是在 IMO 重新发明轮子。

    lodash 油门

    创建一个限制函数,每等待毫秒最多只调用一次 func。节流函数带有一个取消方法来取消延迟调用。提供一个选项对象以指示 func 应在等待超时的前沿和/或后沿调用。对受限制函数的后续调用将返回上一次 func 调用的结果。

    来自他们自己网站的示例:

    // avoid excessively updating the position while scrolling
    jQuery(window).on('scroll', _.throttle(updatePosition, 100));
    
    // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
    jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
      'trailing': false
    }));
    
    // cancel a trailing throttled call
    jQuery(window).on('popstate', throttled.cancel);
    

    【讨论】:

    • 哦!这正是我想要的!谢谢!
    【解决方案2】:

    使用之前的 @bhantol 非常有价值的响应,以及其他一些 stackoverflow 响应 (https://stackoverflow.com/a/43638411/803195),我发布了一个示例代码来模拟我真正想要的行为。

    也许它在最初的问题上没有很好地定义,但我需要实际使用 debounce 并且它必须是动态的,取决于一些变量(以下示例中的复选框)它必须是“延迟”或“立即”:

    https://codepen.io/mtomas/pen/xYOvBv

    var debounced = _.debounce(function() {
      display_info($right_panel);
    }, 400);
    $("#triggerEvent").click(function() {
      if (!$("#chk-immediate").is(":checked")) {
        debounced();
      } else {
        display_info($right_panel, true);
      }
    });
    

    该示例基于该(有趣的)文章上发布的原始示例:

    https://css-tricks.com/debouncing-throttling-explained-examples/

    -- 更新-- 使用 lodash 的 debounce 意味着我要导入完整的 lodash(最小化 72Kb),所以我使用这个参考实现了一个“lite”自己的 debounce:

    https://davidwalsh.name/function-debounce

    function debounce(func, wait, immediate) {
        var timeout;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
    

    我也更新了我的 codepen 测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 2012-07-23
      • 2021-10-29
      • 1970-01-01
      相关资源
      最近更新 更多