AngularJS:$ debow debounce

时间:2015-04-21 11:32:03

标签: javascript angularjs watch

我有以下html代表搜索字段:

<input ng-model-options="{ debounce: 500 }" type="text" ng-model="name">

以下是js:

$scope.$watch('name', function(newVal, oldVal) {
            if(newVal != oldVal) {
                $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
            }
        });

现在,我的pageChanged函数对我的服务器进行REST调用,并根据排序和搜索信息返回一个entites列表(&#34; name&#34;)。假设我的用户想要搜索&#34; Tom&#34;。我想避免我的应用程序进行三次休息呼叫(名称=&#34; T&#34;,名称=&#34; To&#34;,name =&#34; Tom&#34;)。

我尝试使用debounce进行此操作,但似乎手表没有使用去抖动,所以我想知道用最少的代码实现这个的最佳方法是什么?

2 个答案:

答案 0 :(得分:6)

你应该使用ng-change来做这种事情而不是连接手表。

<input ng-model-options="{ debounce: 500 }" type="text" ng-model="name" ng-change="modelChanged()">

JS:

var timeout = $timeout(function(){});

$scope.modelChanged = function(){
    $timeout.cancel(timeout); //cancel the last timeout
    timeout = $timeout(function(){
        $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
    }, 500);
};

我不熟悉去抖动,但它可能会达到同样的效果。

答案 1 :(得分:2)

非常有趣的用例!

<强>解决方案:

我通过在服务中实施debounce功能从lodash&#39;中获取灵感,解决了类似的问题。实施(也可以找到implementation here(@Pete BD&#39;答案)。

// Create an AngularJS service called debounce
app.factory('debounce', ['$timeout','$q', function($timeout, $q) {
  // The service is actually this function, which we call with the func
  // that should be debounced and how long to wait in between calls
  return function debounce(func, wait, immediate) {
    var timeout;
    // Create a deferred object that will be resolved when we need to
    // actually call the func
    var deferred = $q.defer();
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        if(!immediate) {
          deferred.resolve(func.apply(context, args));
          deferred = $q.defer();
        }
      };
      var callNow = immediate && !timeout;
      if ( timeout ) {
        $timeout.cancel(timeout);
      }
      timeout = $timeout(later, wait);
      if (callNow) {
        deferred.resolve(func.apply(context,args));
        deferred = $q.defer();
      }
      return deferred.promise;
    };
  };
}]);

然后我将它包含在包含$watch的控制器/指令中,然后像这样做(使用你的代码):

$scope.$watch('name', debounce(function(newVal, oldVal) {
   if(newVal != oldVal) {
     $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
   }
}, 500));

完成!

案例记录:

我也尝试过这样做:

$scope.$watch('name', function(newVal, oldVal) {

   debounce(function() {
     if(newVal != oldVal) {
       $scope.pageChanged($scope.sort, $scope.name, $scope.sortDirection);
     },500)();
});

但不满意,因为手表在50ms内运行了两次。