控制器中的AngularJS SET服务变量,并且在没有$ watch的情况下使用GET到其他地方

时间:2017-08-28 08:34:45

标签: angularjs service controller directive watch

这是我设置和获取值的基本服务:

.controller('global', ['$scope', '$http', '$api', '$location', '$translate', '$rootScope', '$timeout', '$filter', 'toastr', '$window', 'flag', 'companyService', function ($scope, $http, $api, $location, $translate, $rootScope, $timeout, $filter, toastr, $window, flag, companyService) {
$api('GetCompanyOptions', {})
    .then(function (response) {
      $scope.companyOptions = response.data
      // doing stuff with the response first
      // ...
      // and setting the value to companyService
      companyService.setOptions($scope.companyOptions)
    })
}])

在全局控制器中,我调用我的$ api工厂,该工厂发出http请求(带有承诺)来获取和设置公司选项。我这样做只有一次。

$scope.companyOptions = companyService.options

现在几乎在每个控制器和指令中我都想使用这个值。但是因为http调用需要一段时间,我在时间上遇到了很多问题,所以有时我会得到以下的空值:(是的,在html中它自动使用$ apply和变量不是空的,但在控制器内部它是)

$scope.$watch(function () { return companyService.options }, function (newVal) {
  // checking if companyService.options is still empty or not
  if (!$.isEmptyObject(newVal)) {
    // Now the options is filled, do some stuff...
  }
})

我尝试了很多解决方案,例如使用$ watch,$ timeout,promises,$ rootScope等。但是除了在每个控制器和指令中使用$ watch之外我都没有工作:

{{1}}

所以我的问题是:

  1. 在每个控制器中使用$ watch正在运行。但它有点乱,所以有什么方法可以摆脱它们吗?
  2. 不是在每个控制器/指令中使用$ watch,我可以在服务中使用它吗?
  3. 如果'options'为空,在服务中调用http请求更有意义吗?这样我可以使用诺言? (但我不喜欢这个选项,因为其他功能我更好地在全局控制器中获取/设置companyOptions)。

1 个答案:

答案 0 :(得分:1)

在尝试了很多解决方案后,我认为以下最适合我。我希望它可能对其他人有用。

我决定在ngStorage(https://github.com/gsklee/ngStorage)而不是服务中持有公司选项。

所以这个:

companyService.setOptions($scope.companyOptions)

改为:

$scope.$storage.companyOptions = $scope.companyOptions

然后我在下面的代码的帮助下使用了全局路由解析,这样这段代码就可以在'之前使用。发生实际路由。 (工厂被称为checkToken,因为我也在这里做一个http请求来检查用户令牌是否有效):

  Routes.config(['$routeProvider', function ($routeProvider) {
  var originalWhen = $routeProvider.when
  $routeProvider.when = function (path, route) {
    route.resolve || (route.resolve = {})
    angular.extend(route.resolve, {
      checkToken: ['$checkToken', function ($checkToken) {
        return $checkToken.checkToken()
      }]
    })
    return originalWhen.call($routeProvider, path, route)
  }
}])

这就是工厂本身,在那里我也会关注公司的选择。并在准备好后转到页面:

 .factory('$checkToken', ['$q', '$timeout', '$location', '$api', '$rootScope', '$localStorage', function ($q, $timeout, $location, $api, $rootScope, $localStorage) {
  return {
    checkToken: function () {
      var deferred = $q.defer()
      $api('IsTokenValid', {})
      .then(function (response) {
          // some unrelated codes here...
          // watching companyoptions in localStorage
          $rootScope.$watch(function () { return $localStorage.companyOptions }, function (newVal) {
            if (!$.isEmptyObject(newVal)) {
              // now that we have companyOptions, resolve and go to page
              deferred.resolve('go to page!')
            }
          }, true)
      })
      return deferred.promise
    }
  }
}])

最后,感谢这个解决方案,在我的控制器中,这个:

$scope.$watch(function () { return companyService.options }, function (newVal) {
  // checking if companyService.options is still empty or not
  if (!$.isEmptyObject(newVal)) {
    // Now the options is filled, do some stuff...
  }
})

成为这个,我摆脱了公司服务工厂:

$scope.companyOptions = $scope.$storage.companyOptions