How share Service dynamic data between Controllers

2019-08-16 08:13发布

问题:

I'd like to know what pattern to use, if I need my Service to share it's dynamic data between Controller, Directives, etc. The reason I mention dynamic, is because I'd like to load new data and this data needs to be available in any other Controller, Directive, etc. For example, if a Directive generates a UL LI, it would have to re-generate it if the data inside the Service has changed!

I've initially opened the following ( How to create reset() method in Service that return promise? ) and someone pointed to me that I should use the Observer Pattern. Which I'm very grateful and I wrote this very quickly as a spike of what I need to do and comments would be extremely appreciated ( http://jsbin.com/epAMaP/1 )

var MyApp = angular.module('MyApp', []);

MyApp.config(function($locationProvider){

  $locationProvider.hashPrefix('!');

});

MyApp.factory('MyService', function($timeout){

    var data;

    var loadData = function(){

        data = {
            foo: "bar",
            time: new Date()
        };

        return data;

    };

    return {

        refresh: function(){

            loadData();

        },

        getData: function(){

            return loadData();

        }

    };

});

MyApp.controller('MyCtrl', function($scope,MyService,$timeout){

  $scope.foo = "Service share data";

  $scope.data = MyService.getData();

  $scope.$on("eventFoo", function(){
    console.log("Data has changed!");
    console.log($scope.data);
  });

  $timeout(function(){
    MyService.refresh();
    $scope.$apply(function(){
        $scope.data = MyService.getData();

        $scope.$emit("eventFoo");
    });
  }, 3000);

});

MyApp.directive('myDirective', function(MyService,$timeout){

    return {
        restrict: 'A',
        link: function(scope, elem, attrs){
            scope.$on("eventFoo", function(){
                console.log("Event foo triggered!");

                scope.data = MyService.getData();

                console.log(scope.data);
            });
        }
    };

});

I think this would solve most of my problems but there's something that I need to remember. The data that I'll load comes from $http GET, so I think that I need to use at least a promise every time I need to update or load data, then trigger the right event.

My lack of experience with AngularJs drive me into question my thoughts, so any help or advice is extremely appreciated!

Thanks for looking!

回答1:

I think I found a possible answer, using promise and the Observer Pattern (if this is correct and describes what I'm doing):

var MyApp = angular.module('MyApp', []);

MyApp.config(function($locationProvider){

  $locationProvider.hashPrefix('!');

});

MyApp.factory('MyService', function($q,$timeout,$rootScope){

    var deferred;
    var data;

    var loadData = function(){

        data = {
            foo: "bar" +  Math.floor((Math.random()*100)+1),
            time: new Date()
        };

        deferred.resolve(data);

    };

    return {

        getPromise: function(){

            deferred = $q.defer();
            loadData();

            return deferred.promise;

        },

        getData: function(){

            return data;

        }

    };

});

MyApp.controller('MyCtrl', function($scope,MyService,$timeout){

  $scope.foo = "Service share data";

  MyService.getPromise().then(function(data){
    $scope.data = data;
    console.log("Initial data request:");
    console.log($scope.data);
    $scope.$emit("eventFoo");
  });

  // then after awhile a user requests updated data
  $timeout(function(){

    console.log("// then after awhile a user requests updated data");

    $scope.$apply(function(){

        MyService.getPromise().then(function(data){

            $scope.data = MyService.getData();
            $scope.$emit("eventFoo");

        });         

    });
  }, 3000);

});

MyApp.directive('myDirective', function(MyService,$timeout){

    return {
        restrict: 'A',
        link: function(scope, elem, attrs){
            scope.$on("eventFoo", function(){
                console.log("Event foo triggered!");

                scope.data = MyService.getData();

                console.log(scope.data);
            });
        }
    };

});

You can find the code live at http://jsbin.com/ahiYiBu/1/

Any tips or advice are extremely appreciate it,

Thanks a lot for your time :)



回答2:

I don't know if this helps but I recently shared data between two controllers and a service by using

$rootScope.$broadcast to fire and $scope.$on to catch changes

as far as I can tell it is Angular's implementation of the observer pattern