实现$ scope的延迟。$ watch

时间:2013-12-05 10:18:16

标签: angularjs

我想知道是否有可能在$ scope上实施轻微延迟。$ watch。我有以下查询服务器,所以我想在查询服务器之前评估query之前稍微延迟。我注意到如果你快速键入它会让人感到困惑并且不会发送正确的信息:

$scope.$watch("query", function () {
    $scope.loading = true;
    returnFactory.query($scope.query).then(function (returns) {
        $scope.returns = returns;
        $scope.loading = false;
    });
});

5 个答案:

答案 0 :(得分:32)

通常情况下我会说这个延迟会使用angular的$ timeout,但你还是不能清除这个超时。

//编辑:你可以。

如果此观察者被快速触发,则设置超时并清除它。

像这样:

var timeoutCode;
var delayInMs = 2000;
$scope.$watch("query", function(query) {
 clearTimeout(timeoutCode);  //does nothing, if timeout alrdy done
 timeoutCode = setTimeout(function(){   //Set timeout
     $scope.loading = true;
     returnFactory.query(query).then(function(returns) {
       $scope.returns = returns;
       $scope.loading = false;
     });
 },delayInMs);
});

http://jsfiddle.net/4FuyY/

更新感谢stewie 这可以通过angular的$ timeout来实现。

    var timeoutPromise;
    var delayInMs = 2000;
    $scope.$watch("query", function(query) {
     $timeout.cancel(timeoutPromise);  //does nothing, if timeout alrdy done
     timeoutPromise = $timeout(function(){   //Set timeout
         $scope.loading = true;
         returnFactory.query(query).then(function (returns) {
           $scope.returns = returns;
           $scope.loading = false;
         });
     },delayInMs);
    });

答案 1 :(得分:12)

你可以使用ng-model-option,如果模型'query'是Html标签或Angular指令,对于Ej:

<input type ng-model="query" ng-model-options="{ updateOn: 'default blur', debounce: { 'default':
 2000, 'blur': 1 } }" />

您可以在此处查看Angular Doc:https://docs.angularjs.org/api/ng/directive/ngModelOptions

答案 2 :(得分:7)

我喜欢使用Lo-Dash,它提供了两个非常实用的功能:debouncethrottle,它们完全符合您的要求。假设你想确保它每150毫秒只调用一次函数:

function update() {
 $scope.loading = true;
    returnFactory.query($scope.query).then(function (returns) {
        $scope.returns = returns;
        $scope.loading = false;
    });
}

$scope.$watch("query", function () {
   _.throttle(update, 150);
});

throttle函数可让您控制何时调用update函数(尾随或前沿)。

我在我的应用中一直使用Lo-Dash。它对我来说是一个必备的库...比jQuery更有用。但是,如果您不想包含整个库,则可以创建一个仅包含throttledebounce函数的Lo-Dash自定义版本。

答案 3 :(得分:1)

您可以使用query的当前值来决定何时触发呼叫:

$scope.$watch("query", function (value) {

    //implement rule here for value
    //example value is at least 3 characters
    if (value && value.length > 3) {

        $scope.loading = true;
        returnFactory.query($scope.query).then(function (returns) {
            $scope.returns = returns;
            $scope.loading = false;
        });
    }
});

答案 4 :(得分:0)

我发现对于类似案例有用的片段:

function watchWithDelay(scope, prop, callback, delayMs) {
  delayMs = delayMs || 1000;
  var lastTimeChanged = new Date();
  scope.$watch(prop, function(n, o) {
    lastTimeChanged = new Date();
    setTimeout(function() {
      var diff = new Date().getTime() - lastTimeChanged.getTime();
      if (diff < delayMs-100 || diff > delayMs+100) {
        return;
      }
      callback(n, o);
    }, delayMs);
  });
}

你可以在这样的控制器中使用它:

watchWithDelay($scope, 'client.phone', function(n, o) {
  if (n === o) {
    return;
  }
  // any custom validations, for example
  if (!n) {
    return alert('Phone is required');
  }
  if (n.length < 11) {
    return alert('Phone is shorter than 11 digits');
  }
  // here I should save it somehow
  console.log('Phone is changed to ' + n);
});