如何延迟AngularJS即时搜索?

bra*_*omb 147 search timeout filter delay angularjs

我是AngularJS的新手,我有一个性能问题似乎无法解决.我有即时搜索,但它有点滞后,因为它开始搜索每个keyup().

JS:

var App = angular.module('App', []);

App.controller('DisplayController', function($scope, $http) {
$http.get('data.json').then(function(result){
    $scope.entries = result.data;
});
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:searchText">
<span>{{entry.content}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

JSON数据甚至不是那么大,只有300KB,我认为我需要做的是在搜索上等待用户完成输入的延迟约1秒,而不是在每次击键时执行操作.AngularJS在内部执行此操作,在阅读了此处的文档和其他主题后,我找不到具体的答案.

我很感激有关如何延迟即时搜索的任何指示.谢谢.

Jos*_*rra 297

UPDATE

现在它比以往更容易(Angular 1.3),只需在模型上添加去抖动选项.

<input type="text" ng-model="searchStr" ng-model-options="{debounce: 1000}">

更新了plunker:http://plnkr.co/edit/4V13gK

有关ngModelOptions的文档:https://docs.angularjs.org/api/ng/directive/ngModelOptions

老方法:

这是另一种方法,除了角度本身之外没有依赖关系.

您需要设置超时并将当前字符串与过去的版本进行比较,如果两者相同则执行搜索.

$scope.$watch('searchStr', function (tmpStr)
{
  if (!tmpStr || tmpStr.length == 0)
    return 0;
   $timeout(function() {

    // if searchStr is still the same..
    // go ahead and retrieve the data
    if (tmpStr === $scope.searchStr)
    {
      $http.get('//echo.jsontest.com/res/'+ tmpStr).success(function(data) {
        // update the textarea
        $scope.responseData = data.res; 
      });
    }
  }, 1000);
});
Run Code Online (Sandbox Code Playgroud)

这进入你的观点:

<input type="text" data-ng-model="searchStr">

<textarea> {{responseData}} </textarea>
Run Code Online (Sandbox Code Playgroud)

强制性的掠夺者:http://plnkr.co/dAPmwf

  • 是否存在多个模型更改可能堆叠的问题,从而导致重复请求?在@JasonAden的回答中,他通过取消之前排队的事件来解决这个问题. (3认同)
  • 对我而言,这比接受的答案要容易得多:)谢谢! (2认同)

Jas*_*den 121

(有关Angular 1.3解决方案,请参阅下面的答案.)

这里的问题是每次模型更改时都会执行搜索,这是输入上的每个键盘操作.

有更简洁的方法可以做到这一点,但最简单的方法可能是切换绑定,以便在控制器内部定义$ scope属性,过滤器在其上运行.这样您就可以控制$ scope变量的更新频率.像这样的东西:

JS:

var App = angular.module('App', []);

App.controller('DisplayController', function($scope, $http, $timeout) {
    $http.get('data.json').then(function(result){
        $scope.entries = result.data;
    });

    // This is what you will bind the filter to
    $scope.filterText = '';

    // Instantiate these variables outside the watch
    var tempFilterText = '',
        filterTextTimeout;
    $scope.$watch('searchText', function (val) {
        if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

        tempFilterText = val;
        filterTextTimeout = $timeout(function() {
            $scope.filterText = tempFilterText;
        }, 250); // delay 250 ms
    })
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:filterText">
    <span>{{entry.content}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)


Mic*_*ård 34

在Angular 1.3中我会这样做:

HTML:

<input ng-model="msg" ng-model-options="{debounce: 1000}">
Run Code Online (Sandbox Code Playgroud)

控制器:

$scope.$watch('variableName', function(nVal, oVal) {
    if (nVal !== oVal) {
        myDebouncedFunction();
    }
});
Run Code Online (Sandbox Code Playgroud)

当msg范围变量发生变化时,基本上你会告诉angular运行myDebouncedFunction().属性ng-model-options ="{debounce:1000}"确保msg每秒只能更新一次.


Ali*_*avi 10

 <input type="text"
    ng-model ="criteria.searchtext""  
    ng-model-options="{debounce: {'default': 1000, 'blur': 0}}"
    class="form-control" 
    placeholder="Search" >
Run Code Online (Sandbox Code Playgroud)

现在我们可以设置ng-model-options debounce随着时间的推移和模糊时,模型需要立即更改,否则保存它将具有较旧的值,如果延迟没有完成.


小智 8

对于那些在HTML标记中使用keyup/keydown的人.这不使用手表.

JS

app.controller('SearchCtrl', function ($scope, $http, $timeout) {
  var promise = '';
  $scope.search = function() {
    if(promise){
      $timeout.cancel(promise);
    }
    promise = $timeout(function() {
    //ajax call goes here..
    },2000);
  };
});
Run Code Online (Sandbox Code Playgroud)

HTML

<input type="search" autocomplete="off" ng-model="keywords" ng-keyup="search()" placeholder="Search...">
Run Code Online (Sandbox Code Playgroud)


lge*_*man 6

angularjs的去抖/限制模型更新:http://jsfiddle.net/lgersman/vPsGb/3/

在你的情况下,没有什么比在jsfiddle代码中使用指令更多的事情,如下所示:

<input 
    id="searchText" 
    type="search" 
    placeholder="live search..." 
    ng-model="searchText" 
    ng-ampere-debounce
/>
Run Code Online (Sandbox Code Playgroud)

它基本上是一小段代码,由一个名为"ng-ampere-debounce"的角度指令组成,利用http://benalman.com/projects/jquery-throttle-debounce-plugin/,它可以附加到任何dom元素.该指令重新排序附加的事件处理程序,以便它可以控制何时限制事件.

您可以使用它进行限制/去抖动*模型角度更新*角度事件处理程序ng- [event]*jquery事件处理程序

看看:http://jsfiddle.net/lgersman/vPsGb/3/

该指令将成为Orangevolt Ampere框架的一部分(https://github.com/lgersman/jquery.orangevolt-ampere).


Mor*_*ani 6

仅适用于此处重定向的用户:

您在介绍中Angular 1.3可以使用ng-model-options属性:

<input 
       id="searchText" 
       type="search" 
       placeholder="live search..." 
       ng-model="searchText"
       ng-model-options="{ debounce: 250 }"
/>
Run Code Online (Sandbox Code Playgroud)


小智 5

我相信解决这个问题的最好方法是使用Ben Alman的插件jQuery油门/去抖动.在我看来,没有必要推迟表格中每个字段的事件.

只需将$ scope. $ watch处理函数包装在$ .debounce中,如下所示:

$scope.$watch("searchText", $.debounce(1000, function() {
    console.log($scope.searchText);
}), true);
Run Code Online (Sandbox Code Playgroud)