【问题标题】:Share a single service between multiple angular.js apps在多个 angular.js 应用程序之间共享一个服务
【发布时间】:2026-01-05 03:30:01
【问题描述】:

我正在构建一个电子商务网站(基于 shopify),并且我正在使用多个小型 angularjs 应用程序来处理诸如快速购物车、愿望清单、过滤产品和其他一些较小的项目之类的事情。我最初使用的是一个大型应用程序(具有路由和所有功能),但是当我没有完整的 REST API 时,它有点限制。

我想在 Angular 应用程序之间共享一些服务(购物车服务,因此我可以有一个快速添加按钮,该按钮将反映在迷你购物车等中),但我不确定最好的方法(如果有办法)来解决这个问题。仅与服务共享模块不会在应用程序之间保持相同的状态。

我试过了,但它似乎没有更新两个应用程序之间的状态。以下是我尝试使用的 javascript。它也在带有 html 的 jsfiddle 上:http://jsfiddle.net/k9KM7/1/

angular.module('test-service', [])
  .service('TestService', function($window){
    var text = 'Initial state';

    if (!!$window.sharedService){
      return $window.sharedService;
    }

    $window.sharedService = {
      change: function(newText){
        text = newText;
      },
      get: function(){
        return text;
      }
    }

    return $window.sharedService;
  });

angular.module('app1', ['test-service'])
  .controller('App1Ctrl', function($scope, TestService){
    $scope.text = function(){ return TestService.get() }
    $scope.change = function(){ TestService.change('app 1 activated') }
  });

angular.module('app2', ['test-service'])
  .controller('App2Ctrl', function($scope, TestService){
    $scope.text = function(){ return TestService.get() }
    $scope.change = function(){ TestService.change('app 2 activated') }
  });

var app1El = document.getElementById('app1');
var app2El = document.getElementById('app2');

angular.bootstrap(app1El, ['app1', 'test-service']);
angular.bootstrap(app2El, ['app2', 'test-service']);

任何帮助将不胜感激

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    sharedService 正在共享,但一个 Angular 应用程序不知道另一个应用程序中的更新,因此它不会启动 $digest。您必须通过调用$rootscope.$apply() 手动告诉每个应用程序的$rootScope 启动$digest

    小提琴:http://jsfiddle.net/pvtpenguin/k9KM7/3/

      angular.module('test-service', [])
      .service('TestService', function($rootScope, $window){
        var text = 'Initial state';
        $window.rootScopes = $window.rootScopes || [];
        $window.rootScopes.push($rootScope);
    
        if (!!$window.sharedService){
          return $window.sharedService;
        }
    
        $window.sharedService = {
          change: function(newText){
            text = newText;
            angular.forEach($window.rootScopes, function(scope) {
              if(!scope.$$phase) {
                  scope.$apply();
              }
            });
          },
          get: function(){
            return text;
          }
        }
    
        return $window.sharedService;
      });
    

    【讨论】:

    • 效果很好。你会如何建议我用多个共享服务做 $window.rootScopes 的事情?如果我不小心,我想它会翻倍
    • 啊,别担心,我想出了一个好方法——把它放在应用程序的运行块中,而不是共享模块中
    • @TomBrunoli 你能详细说明你做了什么吗?你是如何将服务代码从共享模块移动到应用程序的运行块而不出错的?
    • @kevin11 我希望我能提供帮助,但我不再拥有代码。我们最终将所有内容重新分解为一个应用程序。我可能应该在获得解决方案时发布我的解决方案……
    • 我知道这真的很旧,但不确定它是如何工作的。当我尝试这个时,每个 windowService rootScope 集合只包含每个模块添加的一个 rootScope,而其他模块没有其他 rootScope 元素。
    【解决方案2】:

    我试图解决类似的问题。在不同 iFrame 中运行的应用程序之间共享工厂。我希望任何帧中的任何$apply() 都会在所有其他帧中引起摘要循环。允许简单的ng-clicks 直接绑定到工厂方法以更新所有其他帧中的视图。我创建了一个处理范围绑定和工厂共享的模块:

    Click here to see plunkr

    只需在每个应用程序中包含该模块:

    angular.module('App', ['iFrameBind'])
    

    并更改任何工厂的 return 语句以返回该工厂的共享版本:

    return sharedFactory.register('counter', service);
    

    例如

    .factory('counter', function (sharedFactory) {
    
      var service;
      var val = 0;
    
      function inc() {
        val++;
      }
    
      function dec() {
        val--;
      }
    
      function value() {
        return val;
      }
    
      service = {
        inc: inc,
        dec: dec,
        value: value
      };
    
      return sharedFactory.register('counter', service);
    })
    
    .directive('counter', function (counter) {
      return {
        template: '{{counter.value()}} ' +
                  '<button ng-click="counter.inc()">Up</button> ' +
                  '<button ng-click="counter.dec()">Down</button> ',
        restrict: 'E',
        link: function postLink(scope) {
          scope.counter = counter;
        }
      };
    });
    

    当点击发生在两个框架中时,计数器更新

    【讨论】: