2014-04-07 53 views
4

我在我的应用程序中使用角度js。在ng-change事件中,我正在调用webservice并基于呈现html的响应。但是在这种情况下,如果我们输入速度太快而导致浏览器等待,则这种调用太频繁。这在Chrome和Mozilla中不是问题。有人能帮我一下吗?角度js ng变化事件

+0

请确保您有不要在ng-change事件中使用'{{}}'。 http://stackoverflow.com/questions/17785617/why-is-angular-js-calling-my-function-so-frequently-with-ng-change-and-how-do-i –

回答

2

你想用一个反跳的图案,沿着这些线路:

.factory('myFactory', function($http) { 
    var debounce; 
    var doRequest = function() { 
    clearTimeout(debounce); 
    setTimeout(function() { 
     // Make HTTP call here 
    }, 333); 
    }; 
    return { 
    doRequest: doRequest 
    }; 
}); 

这样做是发送请求333毫秒后的最后一次它被调用。如果您在每次更改时都调用它,则会在请求之间添加一点间距,从而优化应用程序。

333是Google用于文本输入的内容,随时随地查看值并查看哪些最适合您。

+1

是不是你是每次创建一个新变量并试图在这里清除Timeout?我想你应该在这里使用像'this.debounce'这样的全局变量。请解释我是否错了。 –

+0

@Mr_Green你会注意到我使用了一个工厂 - 变量只会被创建一次。更新澄清,虽然 – SomeKittens

+0

嗯看到第一次..需要研究它。顺便说一句,我认为你错过了'{'''var doRequest = function()'。感谢您的解释:) –

6

你可以拨打电话到服务器之前使用超时,并等待用户完成键入:

<input type="text" ng-model="some.thing" ng-change="fetchData()" /> 

app.controller('someCtrl', function ($scope, $timeout) { 
    var fetchDataDelay = 500; // milliseconds 
    var fetchDataTimer; 

    $scope.fetchData = function() { 
     $timeout.cancel(fetchDataTimer); 
     fetchDataTimer = $timeout(function() { 
      // make expensive call to the server... 
     }, fetchDataDelay); 
    }; 
}); 

需要注意的是采用了棱角分明的(而不是setTimeout/clearTimeout$timeout会照顾角消化循环为你(所以你不必打扰自己手动呼叫$apply()$digest())。

0

你应该使用去抖动的方法 - 当你打字太频繁时,服务器不应该点击。当你停止输入并且发生超时时,请求应该被发送到服务器。您可以使用Underscore Debounce feature或在这里做一个自定义的实现:

$scope.loadData = function() { 
    var loadThrottle; 
    clearTimeout(loadThrottle); 
    loadThrottle = setTimeout(function() { 
     $scope.$apply(function() { 
      $scope.getData(); 
     }); 
    }, 500); 
}; 

这里的要求,如果你停止打字和500ms的超时后发生都会被发送。

另一个实现(使用angularized方法):

$scope.loadData = function(timeout) { 
    $scope.counter += 1; 
    var counter = $scope.counter; 
    $timeout(function(){ 
     if (counter === $scope.counter) { 
      $scope.getData(); 
      $scope.counter = 0; 
     } 
    }, timeout ? timeout : 500); 
} 

而且还替代方案是用更通用的方法定制指令,并强调这样的事情:

app.directive('changeTimeout', function() { 
    return { 
     require: 'ngModel', 
     link: function(scope, element, attrs, ctrl) { 
      angular.forEach(ctrl.$viewChangeListeners, function(listener, index) { 
       ctrl.$viewChangeListeners[index] = _.debounce(function() { 
        scope.$apply(attrs.ngChange); 
       }, attrs.changeTimeout || 0) 
      }); 
     } 
    } 
}); 
2

您可以使用$watch$watchCollection到实现现场活动。

在我的理解和使用中,$ watch和$ watchCollection比ng-change更安静。

这里是一个很好的例子,

$scope.$watchCollection('[some_modelname,someother_modelname]',function(){ 
      alert('Changed the input value!'); 
     }); 
$scope.$watch('some_modelname',function(){ 
      alert('Changed the input value!'); 
     }); 

内部HTML,

<input type="text" ng-model="some_modelname" id="someid" name="somenameifneeded" value=""/> 
<input type="text" ng-model="someother_modelname" id="someotherid" name="somenameifneeded" value=""/> 

两个$watch$watchCollection守望着的任何更改输入字段。一旦做出任何更改,触发器将被调用,这将永远不会死..希望这会有所帮助。

5

我也遇到类似的问题,我想执行一个去抖搜索。有点撞头后,这是我做的:

下面标有NG的模型指导我的输入字段

<input ng-model="searchText" ng-model-options="{ debounce: 500 }" type="text" class="form-control" placeholder="Search...">

请注意,我还包括了NG-模型选项=” {debounce:500}“。它以指定的毫秒数量反转对基础模型的更新。 请参阅ng-model-options指令here的文档。现在

,我添加了一个$表是这样的:

$scope.$watch('searchText', function(newValue) { 
     // expensive ajax call 
    }); 

请参考的$文件看here。它注册一个事件侦听器,侦听作为其第一个参数传递的表达式中的任何更改。在这种情况下,'searchText'是与我的输入字段相关联的模型。

在ng-model-options中提到的去抖动,会消除对'searchText'模型的更新,因此它会去除ajax调用(在我的情况下)。

希望它有帮助。 :)

+1

这是正确的答案,但应该注意的是,ng-model-options能够与ng-change一起工作,因此不需要使用$ watch。 :) – sidonaldson

+0

我喜欢这个回答最好。 – Kelt

1

上1/3你有反跳这里NG选项angularjs是一个例子,所以你可以把它添加到您的NG-变化,它会管理它为你

ng-model-options="{debounce: {'default': 500} } 
+0

这很好,但只能使模型脱落。它不会消除改变 – CarComp