Javascript 无法更新角度服务中函数的函数内的值

Javascript 无法更新角度服务中函数的函数内的值,javascript,angularjs,Javascript,Angularjs,我想在控制器之间共享数据,所以通过服务,我可以轻松地获取和设置数据。但是,如果一个数据集由服务中的函数中的一个函数设置,它就不能更新控制器的数据。 像这样: _this.testf = function (){ _this.test.push(1); _this.test.push(1); _this.test.push(1); $timeout(function (){ _this.test.push(2);//this can not seen in control

我想在控制器之间共享数据,所以通过服务,我可以轻松地获取和设置数据。但是,如果一个数据集由服务中的函数中的一个函数设置,它就不能更新控制器的数据。 像这样:

_this.testf = function (){
  _this.test.push(1);
  _this.test.push(1);
  _this.test.push(1);

  $timeout(function (){
    _this.test.push(2);//this can not seen in controller
  }, 1000);
}
新数据仍然可以通过$watch进行更新,但它与reference不同

.controller('MainCtrl', function($scope, $timeout, List) {
    $scope.test = List.test = [];
    List.testf();
    $timeout(function (){
        $scope.test = angular.copy(List.test); 
    }, 4000);
});

下面是示例代码:

这是因为
$timeout
服务是异步的

您可以让您的服务
返回值,然后在控制器中在返回的承诺中设置它,如:

.service('List', function($timeout) {
  var _this = this;

  _this.test = [];
  _this.testf = function (){
    _this.test.push(1);
    _this.test.push(1);
    _this.test.push(1);
    return $timeout(function (){
      _this.test.push(2);
      return _this.test;
    }, 1000);
  }
})
.controller('MainCtrl', function($scope, $timeout, List) {
  List.testf().then(function(test) {
    $scope.test = test;
  });
});

是更新的代码笔。

发生此问题的原因是,在超时时间过后,控制器的摘要周期已经结束。如果您在您的笔中添加了如下快速脏支票:

_this.testf = function (){
    _this.test.push(1);
    _this.test.push(1);
    _this.test.push(1);
    $timeout(function (){
      _this.test.push(2);
      alert(_this.test.length);
    }, 1000);
}
您将看到阵列已更新

因此,您可以在控制器中使用
$watch
$timeout
,或将指令中的事件广播到控制器以触发新的摘要循环

如果使用$timeout,您分配的绑定将无法识别数据已更新(而如果使用深度监视、监视数组长度或使用$watchCollection,$watch将无法识别数据已更新),但您可以通过复制数组强制更新,这实际上是在创建一个全新的引用

.controller('MainCtrl', function($scope, $timeout, List) {
    $scope.test = List.test = [];
    List.testf();
    $timeout(function (){
        $scope.test = angular.copy(List.test); 
    }, 4000);
});

问题是,
ng bind
仅在您传递给它的对象被另一个对象替换时才会更新。因为您正在向它传递一个数组,并且只更新数组的元素
ng bind
将不会更新。您可以通过使用
ng repeat
或使用{{}}代替ng bind来修复此问题

  <p>
    <span ng-repeat="item in test track by $index" ng-bind="item"></span>
  </p>


请检查codepan链接,我认为应该是1,1,1,2,但如果控制器中没有$watch,最后应该是2。我注意到一件奇怪的事情,如果你用{{}替换你的
ng绑定
,它会工作。这个答案揭示了为什么会这样。我仍然不能完全确定为什么会发生这种情况。谢谢,我在控制器中添加了一个$timeout来执行$digest,但仍然不起作用。请检查一下电话号码codepen@DavidL不知道你是什么意思?UI仍然应该是响应的——它只是在操作完成之前不会显示结果。我不是说整个UI,而是说在整个异步调用解决之前,数据不会解决,而OP可能希望立即返回数据集,然后在附加数据过滤器中更新。啊,明白了--当我输入我的回复时,我开始认为这就是你的意思,但我想无论如何我都会发布。