Могу ли я дебоширить или дросселировать наблюдаемый в AngularJS с помощью lodash?
у меня есть следующее, что делает часы на <input>
поле, которое привязано к $scope.id. каждый раз при изменении значения поля ввода выполняется функция watch:
$scope.$watch("id", function (id) {
// code that does something based on $scope.id
});
есть ли способ, которым я могу поставить тайм-аут на это или отменить это с _lodash, чтобы код не выполняется при каждом нажатии клавиши, пока пользователь изменяет значение.
что я хотел бы для задержка в одну секунду, так что после того, как пользователь перестал печатать на одну секунду, то этот блок кода внутри часов работает. Обратите внимание, что входное значение-это то, что может измениться в любой момент. Например, мне нужно вызвать функцию, если значение "1" или "10" или "1000". Это что-то похожее на то, как работает окно поиска с предложениями в Google. Если пользователь вводит 999, то мне нужно вызвать функцию. Если он удаляет 9, так что это 99, то мне нужно вызвать функцию.
у меня есть _lodash доступны, так что решение, которое использует, что может быть лучше подходит для моих нужд.
4 ответа:
это то, что вы ищете?
$scope.$watch("id", _.debounce(function (id) { // Code that does something based on $scope.id // This code will be invoked after 1 second from the last time 'id' has changed. }, 1000));
обратите внимание, однако, что если вы хотите изменить $scope внутри этой функции, вы должны обернуть его
$scope.$apply(...)
Как только_.debounce
функция использует$timeout
внутренне (что, насколько я понимаю, не делает) Angular не будет знать об изменениях, которые вы сделали на$scope
.обновление
что касается обновленного вопроса-да, вам нужно обернуть все тело функции обратного вызова с помощью
$scope.$apply()
:$scope.$watch("id", _.debounce(function (id) { // This code will be invoked after 1 second from the last time 'id' has changed. $scope.$apply(function(){ // Code that does something based on $scope.id }) }, 1000));
вы можете использовать ngModelOptions в угловой 1.3.0
HTML:
<div ng-controller="Ctrl"> <form name="userForm"> Name: <input type="text" name="userName" ng-model="user.name" ng-model-options="{ debounce: 1000 }" /> <button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br /> </form> <pre>user.name = <span ng-bind="user.name"></span></pre> </div>
дополнительная информация:https://docs.angularjs.org/api/ng/directive/ngModelOptions
Я знаю, что вопрос просит решение лодашь. Во всяком случае, вот угловое решение:
app.factory('debounce', function($timeout) { return function(callback, interval) { var timeout = null; return function() { $timeout.cancel(timeout); var args = arguments; timeout = $timeout(function () { callback.apply(this, args); }, interval); }; }; });
в контроллере:
app.controller('BlaCtrl', function(debounce) { $scope.$watch("id", debounce(function (id) { .... }, 1000)); });
вы можете инкапсулировать это в директиве. Источник: https://gist.github.com/tommaitland/7579618
<input type="text" ng-model="id" ng-debounce="1000">
Javascript
app.directive('ngDebounce', function ($timeout) { return { restrict: 'A', require: 'ngModel', priority: 99, link: function (scope, elm, attr, ngModelCtrl) { if (attr.type === 'radio' || attr.type === 'checkbox') { return; } var delay = parseInt(attr.ngDebounce, 10); if (isNaN(delay)) { delay = 1000; } elm.unbind('input'); var debounce; elm.bind('input', function () { $timeout.cancel(debounce); debounce = $timeout(function () { scope.$apply(function () { ngModelCtrl.$setViewValue(elm.val()); }); }, delay); }); elm.bind('blur', function () { scope.$apply(function () { ngModelCtrl.$setViewValue(elm.val()); }); }); } }; });