在$ watch函数中调用$ evalAsync时的无限循环(AngularJS)

时间:2017-09-10 12:23:14

标签: angularjs scope digest

我跟随Tero Parviainen的书"建立你自己的角度"在谈论$ evalAsync时,我很难理解他所介绍的一个概念。

在其中一个例子中,他声明了一个总是调用$ evalAsync的观察者:

it('eventually halts $evalAsyncs added by watches', function() {
  scope.aValue = [1, 2, 3];
  scope.$watch(
    function(scope) {
      scope.$evalAsync(function(scope) { });
      return scope.aValue;
    },
    function(newValue, oldValue, scope) { }
  );
  expect(function() { scope.$digest(); }).toThrow();
});

看到这个例子,我希望摘要周期在观察者中迭代两次直到停止。在范围的实现中,代码一直运行,直到摘要不脏或队列中没有$ evalAsyncs。

Scope.prototype.$digest = function () {
  var ttl = 10;
  var dirty;
  this.$$lastDirtyWatch = null;
  do {
    while (this.$$asyncQueue.length) {
      var asyncTask = this.$$asyncQueue.shift();
      asyncTask.scope.$eval(asyncTask.expression);
    }
    dirty = this.$$digestOnce();
    if ((dirty || this.$$asyncQueue.length) && !(ttl--)) {
      throw '10 digest iterations reached';
    }
  } while (dirty || this.$$asyncQueue.length);
}; 

如果对于循环中的每次迭代,如果一个asyncTask从数组移位,那么该循环如何永远运行?因为$$ asyncQueue被清空了,所以循环不应该停止吗?

希望我明确表达并感谢大家!

1 个答案:

答案 0 :(得分:0)

致电:

scope.$evalAsync(function(scope) { });

您将新项目添加到asyncQueue

asyncQueue.push({scope: this, expression: expr, locals: locals});

所以通过this.$$asyncQueue.shift();删除任务我们调用新的迭代a.e.新的消化周期。

无论如何,观察者的正确实施是:

scope.aValue = [1, 2, 3];
  scope.$watch(
    function(scope) {
      return scope.aValue;
    },
    function(newValue, oldValue, scope) { }
  );