使用 angular 工厂来保存应用程序其余部分访问的值,以最大限度地减少服务器调用

use angular factory to hold a value for rest of application to access to minimize server calls

我有以下工厂:

angularModule
  .factory('ArticleCategoryService', function ($http, $q) {
    // Service logic
    // ...

    var categories = [];

    var _getCategories = $http.get('/api/articles/category').success(function (_categories) {
      categories = _categories;
    });
    // .error( function (data, status, headers, config) {
    // });

    // Public API here
    return {
      getCategories: function () {
        var deferred = $q.defer();
        deferred.resolve(_getCategories);
        return deferred.promise;
      }
    };
  });

这是在控制器中调用此服务的部分:

// Calls the getCategories function from the ArticleCategory Service,
    // Will return a promise
    ArticleCategoryService.getCategories()
      .then(function (categoriesResult) {
        $scope.categories = categoriesResult.data;
      }, function (err) {
        console.log(err);
      });

这可行,但每次用户返回此 view/state 时都会对服务器进行 GET 调用,并且从未使用属于工厂的 categories 对象。

我正在努力让它 return 工厂单例中的 categories 变量,并让它在站点加载时初始化(或从第一次 GET 调用开始)。

但是如果我只是 return categories 当用户调用 getCategories 时,它将 return 什么都没有,因为我们需要时间进行 $http 调用。

检查是否定义了 categories,如果是,则使用变量而不是 GET 请求解析承诺:

return {
    getCategories: function () {
        var deferred = $q.defer();
        if (categories.length > 0) {
            deferred.resolve(categories);
        } else {
            deferred.resolve(_getCategories);
        }
        return deferred.promise;
    }
};
angularModule
  .factory('ArticleCategoryService', function ($http) {
    // Service logic
    // ...

    var categories = [];

    $http.get('/api/articles/category').success(function (_categories) {
      categories = _categories;
    });


    // Public API here
    return {
      categories: categories
    };
  });


angularModule
   .controller('ControllerMain', function($scope, ArticleCategoryService) {

       $scope.categories = ArticleCategoryService.categories;

    });

我在我的应用程序上做着完全相同的事情。我有一个主模块和一个包含任何其他控制器的主控制器,因此它的范围在视图上是持久的。

在这个主控制器中,您可以将工厂的 getCategory() 数据分配给范围变量,然后您可以在整个应用程序中使用它,因为范围将继承到子范围。

angularMainModule
  .factory('ArticleCategoryService', function ($http) {
      var ArticleCategoryServiceMethods = {};

      //fn: getCategories
      ArticleCategoryServiceMethods.getCategories = function(fromWhere){
         return $http.get(fromWhere)
                 .then(function(res){
                     return res.data;
                 }, function(err){
                     return err.status;
                });
      }

      return ArticleCategoryServiceMethods;
}

angularMainModule
   .controller('MAINCTRL', function($scope, ArticleCategoryService) {

    //get all categories
    $scope.categories = ArticleCategoryService.getCategories('/api/articles/category');

   //... the rest of the main ctrl code ... //

}

...当您定义主模块时,请确保将其余模块注入其中

var angularMainModule = angular.module('angularMainModule', [
    'ngRoute',
    'ngTouch',
    'ngAnimate',
    //< ng - etc >,
    'Module1',
    'Module2',
    //< module - n >
]);

...和标记(我正在手动引导我的 angular 应用程序,但是如果您这样做的话,您可以在 html 标签上添加 ng-app="angularMainModule" 属性那样):

<html ng-controller="MAINCTRL">
<!-- head data -->
<body>
<div id="page" ng-view></div>

如果你想确保在你的应用程序打开主页之前加载数据,你可以在你的应用程序的 routeProvider 块中添加该服务调用(在默认路由上),所以当 MAINCTRL将加载数据已经存在,准备分配。