AngularJS:使用不同的服务初始化控制器

时间:2014-08-22 23:16:35

标签: angularjs

我有一个"请等待,正在进行中"页。它使用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的做法是什么?

2 个答案:

答案 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用于此类异步请求。