【问题标题】:jQuery / backbone.js - delay function calljQuery/backbone.js - 延迟函数调用
【发布时间】:2011-07-20 02:35:44
【问题描述】:

我有一个#search 元素,当keyup 事件发生时应该触发一个函数。这个函数应该只在keyup 在设定的时间内没有发生(比如500毫秒)时触发。这将防止搜索结果更新每个按下的字母。问题在于,使用backbone.js,我将我的事件放在哈希中,而适用的事件如下所示:

'keyup #search' : 'setSearch'

当keyup 事件发生时调用setSearch() 函数。我目前还不清楚如何处理它。我已经尝试了很多方法,但没有什么可以保持计时器超过功能结束。

我有这样的事情:

setSearch: function(event) {
            var timer = window.setTimeout( function() {
                // run function here
                alert('fired');
            }, 500);
    },

而不是alert('fired'),我将运行我自己的函数。我可以看到为什么这段代码不起作用(为每个发生的 keyup 事件设置一个计时器。但我仍然不清楚我还能尝试什么。

【问题讨论】:

    标签: javascript jquery backbone.js dom-events settimeout


    【解决方案1】:

    你要找的其实是 underscore.js 提供给你的一个函数(Backbone 的要求)

     setSearch: _.throttle(function() {
                    //Do Stuff
                  }, 500),
    

    简而言之,这将返回一种新形式的匿名函数,该函数只能每 500 毫秒调用一次。您可能需要根据自己的需要调整时间。

    更多信息: http://documentcloud.github.com/underscore/#throttle

    【讨论】:

    • user1243645 的评论:“我在我的项目中遇到了类似的要求。我只是想补充一下,作为对 Skylar Anderson 关于_.throttle 的帖子的回应,我实际上发现_.debounce() 更适合我的需求。”
    • Debounce 在这个问题上远比油门好。
    【解决方案2】:

    您的视图中需要一个实例变量来存储计时器 ID,然后您可以根据需要停止并重新启动它:

    setSearch: function(event) {
        var self = this;
        if(self.timer)
            clearTimeout(self.timer);
        self.timer = setTimeout(function() {
            alert('fired');
            self.timer = null;
        }, 500);
    }
    

    因此,如果计时器已经在运行,您可以调用 clearTimeout 来停止它,启动一个新的计时器,并将计时器 ID 存储在 self.timer(又名 this.timer)中。您还需要在计时器的回调函数中重置存储的计时器 ID,否则您的 setSearch 在其计时器触发一次后不会做任何事情。而所有self的业务只是为了捕获this在定时器的回调函数中使用。

    【讨论】:

      【解决方案3】:

      阻止更新每个keyup 上的搜索结果正是Underscore 的_.debounce(function, wait) 函数旨在处理的那种情况。 underscore documentation for _.debounce() 声明:

      创建并返回传递的function 的新去抖动版本,该版本将推迟其执行,直到自上次调用它起经过wait 毫秒之后。对于实现仅在输入停止到达后才应发生的行为很有用。

      重构后的代码看起来很简单:

      setSearch: function(event) {
          _.debounce(doSomething, 300);
      },
      

      【讨论】:

      • “它将推迟执行,直到自上次调用它以来等待毫秒过去” - 在“搜索字段”的情况下不起作用,因为您不希望它在第一个键位上进行搜索,您希望在进行搜索之前等待 3 个键位等 - 特别是对于大型集合。但万一发生火灾,然后再等待火灾,是的,这很棒。
      【解决方案4】:

      由于您希望事件处理程序事件能够维护事件是否具有recentlyFired,因此您可能希望将处理程序包装到闭包中并保持该状态。触发事件后,状态应更改为 true,并在延迟 500 毫秒后重置为 false。

      setSearch: function( ) {
          var firedRecently = false;
          return function(event) {
              if (firedRecently) {
                  // it has fired recently. Do you want to do something here?
              } else {
                  // not fired recently
                  firedRecently = true;
                  // run your function here
                  alert('fired');
                  var resetStatus = window.setTimeout( function () {
                      firedRecently = false;
                  }, 500);
              }
          }
      }( );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多