我有一个"请等待,正在进行中"页。它使用Angular控制器实现:控制器每隔几秒向服务器发送一次请求,以检查长时间运行的任务是否完成。如果任务完成,则将用户重定向到下一页。还有一项服务,知道"如何检查作业的状态。控制器和服务的简化版本:
controller('MyCtrl', ["$scope", "$timeout", "MyService",
function($scope, $timeout, MyService) {
$scope.checkStatus = function() {
var request = MyService.fetch_status();
request.success(function(statusData) {
if (statusData.in_progress) {
$timeout(function() {
$scope.checkStatus();
}, 2000)
} else {
window.location = statusData.redirect_to;
}
});
};
$scope.checkStatus();
}]);
factory('MyService', ['$http', function($http){
return {
fetch_status : function() {
return $http({
url: '/job_status',
method: 'GET',
headers: { 'Accept': 'application/json' }
});
}
};
}]);
我想在不同的页面上重用相同的控制器。此新页面看起来非常相似,但它会检查不同长时间运行任务的状态并使用不同的URL。有没有办法用不同的服务初始化同一个控制器,并且知道"如何检查任务的状态?或者有没有办法配置服务以将请求发送到不同的URL? AngularJS的做法是什么?
答案 0 :(得分:1)
您可以使用route parameter"解决"为不同的URL预先配置一些东西
在你的情况下,它会是这样的(可能有错误):
var app = angular.module('app', []);
app.config(function($routeProvider) {
$routeProvider
.when('/link1', {
templateUrl: 'link1.html',
controller: 'MyCtrl',
resolve: {
MyService: MyServiceLink1
}
})
.when('/link2', {
templateUrl: 'link2.html',
controller: 'MyCtrl',
resolve: {
MyService: MyServiceLink2
}
});
)
app.factory('MyServiceLink1', ['$http', function($http){
return {
fetch_status : function() {
return $http({
url: '/job_status',
method: 'GET',
headers: { 'Accept': 'application/json' }
});
}
};
}]);
app.factory('MyServiceLink2', ['$http', function($http){
return {
fetch_status : function() {
return $http({
url: '/other_job_status',
method: 'GET',
headers: { 'Accept': 'application/json' }
});
}
};
}]);
答案 1 :(得分:1)
我认为有一些方法可以满足您的要求
解决方案1
您可以将整个获取状态逻辑移动到MyService.checkStatus(),并且此函数返回一个promise。因此,从任何控制器,您只需要注入MyService并调用checkStatus()函数。
factory('MyService', ['$http', '$q', '$timeout', function($http, $q, $timeout) {
return {
checkStatus : function() {
var deferred = $q.defer();
$http({
url: '/job_status',
method: 'GET',
headers: { 'Accept': 'application/json' }
}).success(function(data) {
if (statusData.in_progress) {
$timeout(function() {
this.checkStatus(url, callback);
}, 2000);
} else {
deferred.resolve(data);
}
}).error(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
};
};
控制器
controller('MyCtrl', ["$scope", "$timeout", "MyService",
function($scope, $timeout, MyService) {
MyService.checkStatus().then(function(statusData) {
// redirect or other logic here
window.location = statusData.redirect_to
}, function(err) {
// handle error
});
;
}]);
解决方案2
使用$rootScope.$broadcast('checkingStatus')
广播事件以开始检查状态。获取状态数据$rootScope.$broadcast('checkStatusCompleted', statusData)
后,还会广播另一个事件。
然后从每个控制器注册监听器
$scope.$on('checkingStatus', function(event, args) {
// show status
});
$scope.$on('checkStatusCompleted', function(event, args) {
// redirect
});
解决方案3
将socket-io用于此类异步请求。