デバウンスによるAngularJS入力スロットル

入力の調整を使用するためのさまざまなシナリオがあり、値が変更されるたびにフィルターが再計算されることはありませんが、それほど頻繁ではありません。 より適切な用語は「デバウンス」です。これは、本質的に、サーバーへの一定のリクエストの「バウンス」を引き起こさないように、関数を呼び出す前に値が一定のレベルで安定することを期待するためです。 この種の標準的なケースは、ユーザーが入力フィールドにテキストを入力して要素のリストをフィルタリングすることです。 フィルターのロジックにオーバーヘッドが含まれる場合(たとえば、バックエンドデータベースでクエリを実行するRESTリソースを介してフィルタリングが発生する場合)、ユーザーがフィールドにテキストを書き込んでいる間、クエリの結果を常に再起動して再ロードする必要はありません。 代わりに、終了するまで待機し、その後リクエストを1回実行する方が適切です。



この問題の簡単な解決策はこちらです: jsfiddle.net/nZdgm



$ scope.searchTextフィールドのテキストを含む何かに基づいて、フィルターされたリスト($ scope.filteredList)として公開するリスト($ scope.list)があるとします。 フォームは次のようになります(現時点ではスロットルチェックボックスに注意しないでください)。



<div data-ng-app='App'> <div data-ng-controller="MyCtrl"> <form> <label for="searchText">Search Text:</label> <input data-ng-model="searchText" name="searchText" /> <input type="checkbox" data-ng-model="throttle"> Throttle <label>You typed:</label> <span>{{searchText}}</span> </form> <ul><li data-ng-repeat="item in filteredList">{{item}}</li></ul> </div> </div>
      
      







典型的なシナリオは、検索フィールドを観察して即座に応答することです。 ろ過方法:



 var filterAction = function($scope) { if (_.isEmpty($scope.searchText)) { $scope.filteredList = $scope.list; return; } var searchText = $scope.searchText.toLowerCase(); $scope.filteredList = _.filter($scope.list, function(item) { return item.indexOf(searchText) !== -1; }); };
      
      







コントローラーは次のように$ watchを設定します



 $scope.$watch('searchText', function(){filterAction($scope);});
      
      







このアプローチは、フィールドに入力するたびにフィルタリングをトリガーします。 状況を改善するために、underscore.jsに組み込まれているdebounce関数を使用します。 この関数は非常に単純です。実行する関数とミリ秒単位の時間を指定します。 これにより、実際の関数呼び出しは、最後に呼び出されてから指定された時間が経過するまで遅延されます。 つまり、1秒の遅延(この例では効果を誇張するために使用します)と、フィールドへのクイックテキスト入力中の関数呼び出しの連続ストリームにより、実際の関数はこれから入力を停止するまで呼び出されません1秒は過ぎません。



次のような簡単なデバウンスを行いたくなるかもしれません。



 var filterThrottled = _.debounce(filterAction, 1000); $scope.$watch('searchText', function(){filterThrottled($scope);});
      
      







ただし、問題があります。 このアプローチは、$ダイジェストサイクルの外側で起動するタイマーを使用するため、Angularは発生した変更を認識しないため、最終的にはUIに影響しません。 代わりに、呼び出しを$ applyでラップする必要があります



 var filterDelayed = function($scope) { $scope.$apply(function(){filterAction($scope);}); };
      
      







その後、$ watchを設定し、入力が停止するとすぐに反応します:



 var filterThrottled = _.debounce(filterDelayed, 1000); $scope.$watch('searchText', function(){filterThrottled($scope);});
      
      







もちろん、ここでの本格的な例には調整を含める必要があります。これにより、「インスタント」フィルタリングと保留の違いを確認できます。 このケースのフィドルは、 jsfiddle.net / nZdgmにあります。



All Articles