请先查看代码
app.js
var app = angular.module('Nimbus', ['ngRoute']);
route.js
app.config(function($routeProvider) {
$routeProvider
.when('/login', {
controller: 'LoginController',
templateUrl: 'templates/pages/login.html',
title: 'Login'
})
.when('/home', {
controller: 'HomeController',
templateUrl: 'templates/pages/home.html',
title: 'Dashboard'
})
.when('/stats', {
controller: 'StatsController',
templateUrl: 'templates/pages/stats.html',
title: 'Stats'
})
}).run( function($q, $rootScope, $location, $route, Auth) {
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
console.log("Started");
/* this line not working */
var canceler = $q.defer();
canceler.resolve();
});
$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
$rootScope.title = ($route.current.title) ? $route.current.title : 'Welcome';
});
})
家庭controller.js
app.controller('HomeController',
function HomeController($scope, API) {
API.all(function(response){
console.log(response);
})
}
)
统计-controller.js
app.controller('StatsController',
function StatsController($scope, API) {
API.all(function(response){
console.log(response);
})
}
)
api.js
app.factory('API', ['$q','$http', function($q, $http) {
return {
all: function(callback) {
var canceler = $q.defer();
var apiurl = 'some_url'
$http.get(apiurl,{timeout: canceler.promise}).success(callback);
}
}
}]);
当我从家搬到stats时,再次API将发送http请求,我有很多这样的http调用,我只粘贴了几行代码。
我需要的是取消中止routechangestart上的所有待处理的http请求或成功
或者其他任何实现方法?
答案 0 :(得分:55)
我为此编写了一些概念性代码。可能需要调整以满足您的需求。我的pendingRequests
服务包含用于添加,获取和取消请求的API,httpService
包裹$http
并确保跟踪所有请求。
通过利用$http
配置对象(docs),我们可以获得取消待处理请求的方法。
我做了一个plnkr,但你需要快速的手指才能看到请求被取消,因为我发现的测试网站通常会在半秒内响应,但你会在devtools网络中看到请求被取消的选项卡。在您的情况下,您显然会触发cancelAll()
对来自$routeProvider
的相应事件的调用。
控制器就是为了展示这个概念。
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();
}
}]);
答案 1 :(得分:15)
您可以使用$http.pendingRequests
来执行此操作。
首先,当您提出请求时,请执行以下操作:
var cancel = $q.defer();
var request = {
method: method,
url: requestUrl,
data: data,
timeout: cancel.promise, // cancel promise, standard thing in $http request
cancel: cancel // this is where we do our magic
};
$http(request).then(.....);
现在,我们取消$routeChangeStart
$rootScope.$on('$routeChangeStart', function (event, next, current) {
$http.pendingRequests.forEach(function(request) {
if (request.cancel) {
request.cancel.resolve();
}
});
});
这样,您也可以通过在请求中不提供“取消”字段来“保护”某个请求被取消。
答案 2 :(得分:8)
我认为这是中止请求的最佳解决方案。它使用了拦截器和$ routeChangeSuccess事件。 http://blog.xebia.com/cancelling-http-requests-for-fun-and-profit/
答案 3 :(得分:0)
请注意我是Angular的新手,所以这可能不是最佳的。 另一个解决方案是: 在$ http请求中添加“timeout”参数,Docs我是这样做的:
在我调用所有Rest服务的工厂中,有这个逻辑。
module.factory('myactory', ['$http', '$q', function ($http, $q) {
var canceler = $q.defer();
var urlBase = '/api/blabla';
var factory = {};
factory.CANCEL_REQUESTS = function () {
canceler.resolve();
this.ENABLE_REQUESTS();
};
factory.ENABLE_REQUESTS = function () {
canceler = $q.defer();
};
factory.myMethod = function () {
return $http.get(urlBase, {timeout: canceler.promise});
};
factory.myOtherMethod= function () {
return $http.post(urlBase, {a:a, b:b}, {timeout: canceler.promise});
};
return factory;
}]);
在角度应用程序配置上我有:
return angular.module('app', ['ngRoute', 'ngSanitize', 'app.controllers', 'app.factories',
'app.filters', 'app.directives', 'ui.bootstrap', 'ngGeolocation', 'ui.select' ])
.run(['$location', '$rootScope', 'myFactory', function($location, $rootScope, myFactory) {
$rootScope.$on('$routeChangeSuccess', function (event, current, previous) {
myFactory.CANCEL_REQUESTS();
$rootScope.title = current.$$route.title;
});
}]);
这样它会捕获所有“路由”更改并停止使用该“计时器”配置的所有请求,以便您可以选择对您来说至关重要的内容。
我希望对某人有所帮助。 此致