javascript - 在 Angular Controller 之间共享大对象

标签 javascript angularjs angularjs-directive xmlhttprequest

我正在尝试使用服务在两个 Controller 之间共享数据。但使用 XHR 更改数据后我没有看到数据更新。

angular    
  .module('appy', [])
  .service('MyService', function($http){
    return {
       dataToChange: {
       },
       ajaxy: function(url){
         var self = this;
         setTimeout(function(){
           console.log('now we are in the service!');
           self.dataToChange = 'something new';
           console.log(this.dataToChange);
         }, 1000);
       }
    };
  })
  .controller('c1', ['$scope', 'MyService', function($scope, MyService){
    $scope.myService = MyService;
    $scope.ajaxy = function(){
      $scope.myService.ajaxy();
    };
  }])
  .directive('dirOne', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirone-temp.html'
    };
  })
  .controller('c2', ['$scope', 'MyService', function($scope, MyService){

      $scope.myData = MyService.dataToChange;  

  }])
  .directive('dirTwo', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirtwo-temp.html'
    };
  });

但是当 ajaxy 进行更新时什么也没有发生。我尝试按照 this question 的推荐进行设置。没有喜悦。我还尝试添加 watch 。

$scope.$watch(function(){
  return MyService.ajaxy();
}, function(oldVal, newVal){
  $scope.somethingToChange = newVal;
  console.log($scope.somethingToChange);
});

但是仍然没有发生任何事情。而且这个物体相当大。我不想$watch它。

JSBIN

最佳答案

当您想要像您尝试做的那样共享数据时,您必须共享一个对象(如您给出的示例)并且永远不要替换该对象。如果您确实替换了服务中的对象,$scope 仍将引用旧对象,这就是您的情况的问题。

  1. 您将 MyService.dataChange 设置为空对象。
  2. 您将该对象注入(inject)到 Controller 的范围内
  3. 当您调用 ajaxy() 时,您将 MyService.dataChange 更改为字符串“something new”。此时,作用域仍然保留对旧对象的引用,而不是对字符串的引用。

要解决此问题,您需要向该对象添加一个属性,而不是替换 MyService.dataChange。当您绑定(bind)到共享对象的该属性时,您会注意到必须运行 ajaxy() 两次。要解决这个问题,您需要使用 Angular $timeout,而不是使用超时。

angular    
  .module('appy', [])
  .service('MyService', function($http, $timeout){
    return {
       // never replace this object, put the values you want to share as a property inside.
       sharedObject: {
         name: 'old value'
       },
       ajaxy: function(url){
         var self = this;
         // use the angular version of $timeout to make sure your scope is in sync
         $timeout(function(){
           console.log('now we are in the service!');
           self.sharedObject.name = 'new value';
           console.log(self.sharedObject);
         }, 1000);
       }
    };
  })
  .controller('c1', ['$scope', 'MyService', function($scope, MyService){
    $scope.myData = MyService.sharedObject;
    $scope.ajaxy = function(){
      MyService.ajaxy();
    };
  }])
  .directive('dirOne', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirone-temp.html'
    };
  })
  .controller('c2', ['$scope', 'MyService', function($scope, MyService){ 
    $scope.myData = MyService.sharedObject;
  }])
  .directive('dirTwo', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirtwo-temp.html'
    };
  });
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body ng-app="appy">
  
  <dir-one ng-controller="c1"></dir-one>
  <hr>
  <dir-two ng-controller="c2"></dir-two>  
  
  <script id="dirone-temp.html" type="text/ng-template">
    template one
    <button ng-click="ajaxy()">something time consuming</button>
    <div>{{myData.name}}</div>
  </script>
  
  <script id="dirtwo-temp.html" type="text/ng-template">
    template two
    <div>{{myData.name}}</div>
  </script>
</body>
</html>

关于javascript - 在 Angular Controller 之间共享大对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36190128/

相关文章:

javascript - 部署时 AngularJs 未捕获错误

angularjs:用于检查用户名是否存在的自定义指令

javascript - 在 Chrome 中调试时避免不相关的文件不起作用

javascript - 无法使用 Socket.IO 发送到 Node 服务器

javascript - 在 IOS 上单击按钮时,iframe 不滚动

javascript - 每当输入更改时 AngularJS ng-change

html - AngularJS 绑定(bind)不安全 :javascript:void(0) when value is javascipt:void(0)

javascript - HTML5 Canvas : How do I merge 2 canvas into 1 (of which 1 is draggable)

angularjs - 如何在 AngularJS 指令测试中模拟点击事件?

javascript - 根据滚动位置更新滚动索引的机制