在AngularJS中跨控制器共享Web服务的数据

时间:2013-09-03 12:09:32

标签: angularjs angularjs-scope angularjs-service angularjs-routing

我在Angular应用程序中遇到两个大问题,我完全陷入困境,希望有人可以帮助我。

  1. 我将从网络服务数据共享到多个控制器的方法存在缺陷,我不知道如何修复它。
  2. 我的指令偶尔无法访问控制器范围内的数据(可能是因为问题1)并且记录为未定义,我认为路由更改发生在范围数据解析之前。
  3. 所以,详情,我有一个Angular应用程序,它提供了一个表格,人们可以在我们的网站上注册他们的酒店,人们可以保存他们的详细信息,然后再回来编辑。

    我的应用设置如下。

    我有控制器和路线:

    • 酒店信息(姓名,地点,费用等)
    • 房间
    • 设施(游泳池,桑拿,蒸汽房等)
    • 所有者详细信息(姓名,电子邮件,银行详细信息)
    • 状况
    • 照片

    我有一个名为“HotelService”的工厂,它调用网络服务来检索/存储有关酒店的数据。

    我想在控制器之间共享数据,所以我一直在$ rootScope中存储在web服务上检索到的数据,我看到人们通常不认为这是“有角度的方式”但是我还没有找到任何其他方法来实现同样的目的。这也使得使用这种技术测试我的控制器变得困难。所以我愿意接受另一种解决方案。

    重要的是,我不想向网络服务提出多个初始“GET”请求。获得数据后,我希望所有控制器都能够访问/更新该数据,用户可以随时从任何控制器保存所有数据。

    一些代码:

    这是我的应用配置:

    app.config(['$routeProvider', function($routeProvider)
    {
      $routeProvider
        .when('/', {
          templateUrl: '/views/info.html',
          controller:  'InfoController'
        })
        .when('/rooms', {
          templateUrl: '/views/rooms.html',
          controller:  'RoomsController'
        })
        .when('/facilities', {
          templateUrl: '/views/facilities.html',
          controller:  'FacilitiesController'
        })
        .when('/proprietor', {
          templateUrl: '/views/proprietor.html',
          controller:  'ProprietorController'
        })
        .when('/available', {
          templateUrl: '/views/available.html',
          controller:  'AvailableController'
        })
        .when('/photos', {
          templateUrl: '/views/photos.html',
          controller:  'PhotosController'
        });
    }]);
    

    这是我的app.run,我在$ rootScope上设置数据:

    app.run(
    ['$rootScope', '$window', 'HotelService',
    function($rootScope, $window, HotelService)
    {
        HotelService.get($window.hotelId).then(function(hotel) {
            $rootScope.data = hotel;
        });
      }
    ]);
    

    这是我的酒店服务代码:

    app.factory('HotelService', ['$http', '$rootScope', function ($http, $rootScope) {
      var hotel = {};
      return {
        get: function(hotelId) {
          premId = (angular.isUndefined(hotelId)) ? 0 : premId;
          return $http.jsonp('/webservice', {
            method: 'GET',
            params: { 'id': hotelId, 'callback': 'JSON_CALLBACK' },
            responseType: 'json'
            })
            .then(function(response) {
                hotel = response.hotel;
                $rootScope.$broadcast('handleSharedHotel', hotel);
                return hotel;
          });
        },
        save: function(data) {
          $rootScope.$broadcast('handleBeforeSaveHotel');
          return $http.jsonp('/webservice?callback=JSON_CALLBACK', {
            method: 'POST',
            data: data,
            responseType: 'json'
          }).then(function(response) {
            hotel = response.data.hotel;
            $rootScope.$broadcast('handleSharedHotel', hotel);
            $rootScope.$broadcast('handleAfterSaveHotel', response);
            return hotel;
          });
        }
      };
    }]);
    

    这是我的酒店信息控制器:

    controllers.InfoController = [
      '$scope', '$window', '$rootScope', '$timeout', 'HotelService',
      function($scope, $window, $rootScope, $timeout, HotelService)
      {
        $scope.data = $rootScope.data;
    
        this.save = function() {
            HotelService.save($scope.data);
        };
    
        $scope.$on('handleSharedHotel', function(events, hotel) {
            $scope.data = hotel;
        });
    
        return $scope.InfoController = this;
    }
    

    ];

    一个非常奇怪的(奇怪的是因为我还没有完全理解Angular中的范围)问题我一直在使用,我的指令在路由更改时没有及时获取数据,因此范围值将返回未定义。只有当我直接从地址栏或链接加载页面时才会发生这种情况,但每次刷新页面时都会发生这种情况。

    非常感谢任何想法。

1 个答案:

答案 0 :(得分:0)

我建议在HotelService内缓存返回的promises,然后在需要返回数据的每个控制器中注入服务。

这意味着只有在您的一个控制器内部调用此部分代码时,才会首次发出请求:

HotelService.get($window.hotelId).then(function(hotel) {
        $rootScope.data = hotel;
});

在所有后续调用中,将返回hotelId中传递的缓存承诺。

<强> [编辑]

get实现缓存的简化示例(只是HotelService方法)(尽管我还没有测试过)。您将不得不对代码库进行一些更改,但想法是:

app.factory('HotelService', ['$http', function ($http) {
    var service = {};

    var hotelPromisesCache = {};

    service.get = function (hotelId) {
        var hotelPromise = hotelPromisesCache[hotelId];

        if (hotelPromise == undefined) {
            hotelPromise = $http.jsonp('/webservice', {
                method: 'GET',
                params: { 'id': hotelId, 'callback': 'JSON_CALLBACK' },
                responseType: 'json'
            });

            hotelPromisesCache[hotelId] = hotelPromise;
        }

        return hotelPromise;
    };

    return service;
}]);

不要忘记在更改酒店数据后从缓存中删除承诺,否则您将恢复缓存,而不是修改版本。