如何在AngularJS中取消$ http请求?

mpm*_*mpm 184 promise cancellation angularjs angular-http angular-promise

给出AngularJS中的Ajax请求

$http.get("/backend/").success(callback);
Run Code Online (Sandbox Code Playgroud)

如果启动另一个请求(相同的后端,例如不同的参数),取消该请求的最有效方法是什么.

lam*_*tor 317

此功能已通过timeout参数添加到1.1.5版本中:

var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve();  // Aborts the $http request if it isn't finished.
Run Code Online (Sandbox Code Playgroud)

  • @RamanChodźka你可以做出承诺; 您可以设置超时以在一段时间后取消承诺,使用JavaScript的本机`setTimeout`函数或Angular的`$ timeout`服务. (15认同)
  • 如果我需要超时和通过承诺手动取消,我该怎么办? (13认同)
  • canceler.resolve()将取消将来的请求.这是一个更好的解决方案:http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx (8认同)
  • Ben Nadel提供更完整解决方案的另一个好例子:http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm (7认同)
  • 不起作用.你能提供一份工作样本吗? (3认同)
  • @Toolkit它将取消未来的请求,因为它已经解决,但如果我们做var canceler = $ q.defer(); 在每次请求之前,它都会起作用. (2认同)

Edw*_*san 10

使用timeout属性取消Angular $ http Ajax在Angular 1.3.15中不起作用.对于那些不能等待修复的人,我正在共享一个用Angular包装的jQuery Ajax解决方案.

该解决方案涉及两项服务:

  • HttpService(围绕jQuery Ajax函数的包装);
  • PendingRequestsService(跟踪挂起/打开的Ajax请求)

这里是PendingRequestsService服务:

    (function (angular) {
    'use strict';
    var app = angular.module('app');
    app.service('PendingRequestsService', ["$log", function ($log) {            
        var $this = this;
        var pending = [];
        $this.add = function (request) {
            pending.push(request);
        };
        $this.remove = function (request) {
            pending = _.filter(pending, function (p) {
                return p.url !== request;
            });
        };
        $this.cancelAll = function () {
            angular.forEach(pending, function (p) {
                p.xhr.abort();
                p.deferred.reject();
            });
            pending.length = 0;
        };
    }]);})(window.angular);
Run Code Online (Sandbox Code Playgroud)

HttpService服务:

     (function (angular) {
        'use strict';
        var app = angular.module('app');
        app.service('HttpService', ['$http', '$q', "$log", 'PendingRequestsService', function ($http, $q, $log, pendingRequests) {
            this.post = function (url, params) {
                var deferred = $q.defer();
                var xhr = $.ASI.callMethod({
                    url: url,
                    data: params,
                    error: function() {
                        $log.log("ajax error");
                    }
                });
                pendingRequests.add({
                    url: url,
                    xhr: xhr,
                    deferred: deferred
                });            
                xhr.done(function (data, textStatus, jqXhr) {                                    
                        deferred.resolve(data);
                    })
                    .fail(function (jqXhr, textStatus, errorThrown) {
                        deferred.reject(errorThrown);
                    }).always(function (dataOrjqXhr, textStatus, jqXhrErrorThrown) {
                        //Once a request has failed or succeeded, remove it from the pending list
                        pendingRequests.remove(url);
                    });
                return deferred.promise;
            }
        }]);
    })(window.angular);
Run Code Online (Sandbox Code Playgroud)

稍后在您的服务中加载数据时,您将使用HttpService而不是$ http:

(function (angular) {

    angular.module('app').service('dataService', ["HttpService", function (httpService) {

        this.getResources = function (params) {

            return httpService.post('/serverMethod', { param: params });

        };
    }]);

})(window.angular);
Run Code Online (Sandbox Code Playgroud)

稍后在您的代码中,您希望加载数据:

(function (angular) {

var app = angular.module('app');

app.controller('YourController', ["DataService", "PendingRequestsService", function (httpService, pendingRequestsService) {

    dataService
    .getResources(params)
    .then(function (data) {    
    // do stuff    
    });    

    ...

    // later that day cancel requests    
    pendingRequestsService.cancelAll();
}]);

})(window.angular);
Run Code Online (Sandbox Code Playgroud)


pko*_*rce 9

$http当前版本的AngularJS不支持取消发出的请求.有一个拉动请求被打开以添加此功能但是这个PR还没有被审查,因此不清楚它是否会进入AngularJS核心.


小智 6

如果要使用ui-router取消stateChangeStart上的待处理请求,可以使用以下内容:

//在服务中

                var deferred = $q.defer();
                var scope = this;
                $http.get(URL, {timeout : deferred.promise, cancel : deferred}).success(function(data){
                    //do something
                    deferred.resolve(dataUsage);
                }).error(function(){
                    deferred.reject();
                });
                return deferred.promise;
Run Code Online (Sandbox Code Playgroud)

//在UIrouter配置中

$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    //To cancel pending request when change state
       angular.forEach($http.pendingRequests, function(request) {
          if (request.cancel && request.timeout) {
             request.cancel.resolve();
          }
       });
    });
Run Code Online (Sandbox Code Playgroud)


Ali*_*rak 6

由于某种原因,config.timeout对我不起作用.我用这种方法:

let cancelRequest = $q.defer();
let cancelPromise = cancelRequest.promise;

let httpPromise = $http.get(...);

$q.race({ cancelPromise, httpPromise })
    .then(function (result) {
...
});
Run Code Online (Sandbox Code Playgroud)

而cancelRequest.resolve()取消.实际上它并没有取消请求,但至少你没有得到不必要的回应.

希望这可以帮助.