AngularJS abort all pending $http requests on route change

前端 未结 4 1971
日久生厌
日久生厌 2020-11-28 03:09

Please go through the code first

app.js

var app = angular.module(\'Nimbus\', [\'ngRoute\']);

route.js

app.config(fu         


        
4条回答
  •  执笔经年
    2020-11-28 03:48

    I put together some conceptual code for this. It might need tweaking to fit your needs. There's a pendingRequests service that has an API for adding, getting and cancelling requests, a httpService that wraps $http and makes sure all requests are tracked.

    By leveraging the $http config object (docs) we can get a way to cancel a pending request.

    I've made a plnkr, but you're going to need quick fingers to see requests getting cancelled since the test-site I found typically responds within half a second, but you will see in the devtools network tab that requests do get cancelled. In your case, you would obviously trigger the cancelAll() call on the appropriate events from $routeProvider.

    The controller is just there to demonstrate the concept.

    DEMO

    angular.module('app', [])
    // This service keeps track of pending requests
    .service('pendingRequests', function() {
      var pending = [];
      this.get = function() {
        return 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.canceller.resolve();
        });
        pending.length = 0;
      };
    })
    // This service wraps $http to make sure pending requests are tracked 
    .service('httpService', ['$http', '$q', 'pendingRequests', function($http, $q, pendingRequests) {
      this.get = function(url) {
        var canceller = $q.defer();
        pendingRequests.add({
          url: url,
          canceller: canceller
        });
        //Request gets cancelled if the timeout-promise is resolved
        var requestPromise = $http.get(url, { timeout: canceller.promise });
        //Once a request has failed or succeeded, remove it from the pending list
        requestPromise.finally(function() {
          pendingRequests.remove(url);
        });
        return requestPromise;
      }
    }])
    // The controller just helps generate requests and keep a visual track of pending ones
    .controller('AppCtrl', ['$scope', 'httpService', 'pendingRequests', function($scope, httpService, pendingRequests) {
      $scope.requests = [];
      $scope.$watch(function() {
        return pendingRequests.get();
      }, function(pending) {
        $scope.requests = pending;
      })
    
      var counter = 1;
      $scope.addRequests = function() {
        for (var i = 0, l = 9; i < l; i++) {
          httpService.get('https://public.opencpu.org/ocpu/library/?foo=' + counter++);  
        }
      };
      $scope.cancelAll = function() {
        pendingRequests.cancelAll();
      }
    }]);
    

提交回复
热议问题