在angular js的搜索功能中处理多个Ajax调用


Handle multiple Ajax calls in search functionality in angular js

我已经为我的angular js应用程序实现了自定义搜索功能。

为此,我调用了一个Ajax请求来获取数据。这个调用发生在change事件上,这就是它多次调用Ajax的原因。

请建议,因为我是新来的角度js。

您可以考虑使用延迟(空闲时间)。比如假设我在搜索文本框中输入。如果我空闲了200ms、400ms或任何你想要的时间,你可以调用AJAX请求。

如果我键入salman,它将调用api 6次。但假设我们会有空闲时间。当用户空闲该特定时间时,我们将调用。

要以角度实现它,可以使用$监视或引导指令

所以你最好给自己一点延迟。正如阿卡什所指出的,你必须选择你认为可以接受的延迟时间。您还需要确保只有在延迟之后才提出请求。

这里有一种方法:

//In your controller
var _timeout;
$scope.fetchSearchResults = function(){
    //We will clear the previous timeout because a key has been pressed
    clearTimeout(_timeout);
    //Set the timeout - if no key is pressed, it will execute. Else the line above will clear it.
    _timeout =  setTimeout(function(){
        var keyword = $scope.searchKeyword.name;
        //Do your AJAX request here

        //We have delayed the request by 400ms - but you can change it as you please.
    }, 400);
}

您的HTML:

<!-- Then in your HTML something similar to: -->
<input ng-model="searchKeyword.name" ng-keyup="fetchSearchResults()" />

编辑:

如果你想走"纯"角度的道路,你可以这样做:

//In your controller
//NOTE: make sure you've injected $timeout into your controller
var _timeout;
$scope.fetchSearchResults = function(){
    //We will clear the previous timeout because a key has been pressed
    $timeout.cancel(_timeout);
    //Set the timeout - if no key is pressed, it will execute. Else the line above will clear it.
    _timeout =  $timeout(function(){
        var keyword = $scope.searchKeyword.name;
        //Do your AJAX request here

        //We have delayed the request by 400ms - but you can change it as you please.
    }, 400);
}

我绝对推荐@jeanpaul对"debouncing"的回答。

除此之外,当您可能有多个并发AJAX请求,并且希望处理最近的一个请求时,可能需要验证响应处理程序中的请求。当响应并不总是按照请求的顺序(即,较早的请求比较晚的请求需要更长的响应时间)时,这一点尤为重要。

解决这个问题的方法是:

var activeRequest;
function doRequest(params){
    // reqId is the id for the request being made in this function call
    var reqId = angular.toJson(params); // I usually md5 hash this
    // activeRequest will always be the last reqId sent out
    activeRequest = reqId; 
    $http.get('/api/something', {data: params})
        .then(function(res){
            if(activeRequest == reqId){
                // this is the response for last request
            }
            else {
                // response from previous request (typically gets ignored)
            }
        });
}

您已经接受了答案,但我想与您分享一些代码。

myapp.factory('formService', ['$http', '$filter', '$q', '$timeout', function ($http, $filter, $q, $timeout) {
    var service = {};
    service.delayPromise = null;
    service.canceler = null;
    service.processForm = function (url, formData, delay) {
        if (service.delayPromise)
          $timeout.cancel(service.delayPromise);
        if (service.canceler)
          service.canceler.resolve();
        service.canceler = $q.defer();
        service.delayPromise = $timeout(function (service) {
          return service;
        }, delay, true, service);
        return service.delayPromise.then(function (service) {
          service.delayPromise = null;
          return $http({
              method  : 'POST',
              url     : url,
              timeout : service.canceler.promise,
              data    : formData
          });
        })
    }
    return service;
]);

它提供了具有processForm功能的formService,并接受urlformDatadelay

processForm功能延迟提交$timeout服务。如果已经存在延迟或未决提交,它只是取消它。

在你的控制器里。

myapp.controller('myCtrl', ['formService', function (formService) {
    $scope.formData = {};
    $scope.pageData = {};
    $scope.$watchCollection('formData', function (formData, oldData, scope) {
      if (!angular.equals(formData, oldData)) {
        var event;
        formService.processForm(formData, event, 500).then(function (response) {
          if (response.data instanceof Object)
            angular.copy(response.data, scope.pageData);
        });
      }
    });
}]);