【问题标题】:Directive is not updated due to "$digest already in progress"由于“$digest 已在进行中”,指令未更新
【发布时间】:2013-09-02 11:43:09
【问题描述】:

在我的控制器中,我将变量“数据”设置为默认值。在我的原始项目中,我使用CouchCorner 从 CouchDB 中获取数据并更新数据。

在一个衍生词中,我观察变量数据并相应地更新元素。 但是,我遇到了“$digest 已经在进行中”的问题,导致指令没有正确更新。我已经找到了很多关于 $digest 问题的信息,但是我找不到任何适合我的问题的答案。

我创建了以下 jsFiddle,它使用 $timeout 而不是实际的 CouchDB 请求: http://jsfiddle.net/cwesM/4/

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

function Ctrl($scope, $timeout) {
$scope.data="Initial";

$timeout(function(){
    $scope.data="Updated"}, 1)
}

App.directive('chart', function(){
    return{
        restrict: 'E',
        link: function(scope, elem, attrs){
            scope.$watch(attrs.ngModel, function(v){
                alert(v)
                elem.html("Data="+v);
            });
        }
   };
});

脚本在 1ms 后将“data”的初始值更改为“Updated”。但是指令没有更新,尽管 $watch 函数被执行了。 有趣的是,如果我删除 alert(),一切都会按预期进行。

如何避免 $digest 的冲突?

【问题讨论】:

  • 我不明白。您链接的 jsFiddle 似乎完全符合我的预期。
  • 请再次按fiddler中的“运行”。有时它第一次工作,但如果再试一次就不行。不知何故,加载/运行时问题。
  • 我已经运行了十几次,都达到了预期的结果(Chrome)。您在哪个浏览器中执行此操作?
  • 好提示!我正在使用 Firefox 17.0.8。将在家里尝试使用最新版本。结果是第一行被正确更新({{data}},但指令仍然是“初始”。我收到 $digest 错误消息。
  • @avanc 你可以试试这个解决方案。 stackoverflow.com/a/17510699

标签: javascript angularjs angularjs-directive


【解决方案1】:

您可以使用在 stackoverflow.com/a/17510699 上发布的解决方案(由 @Dor Cohen 回答)。

我帮你把它和你当前的代码放在一起。

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

function Ctrl($scope, $timeout) {
    $scope.data = "Initial";
    $timeout(function () {
        $scope.data = "Updated"
    }, 1);

    $scope.alert = function (info) {
        alert(info);
    }

    $scope.safeApply = function (fn) {
        var phase = this.$root.$$phase;
        if (phase == '$apply' || phase == '$digest') {
            if (fn && (typeof (fn) === 'function')) {
                fn();
            }
        } else {
            this.$apply(fn);
        }
    };
}

App.directive('chart', function () {
    return {
        restrict: 'E',
        link: function (scope, elem, attrs) {
            scope.$watch(attrs.ngModel, function (v) {
                scope.safeApply(function () {
                    alert(v);
                });
                elem.html("Data=" + v);
            });
        }
    };
});

【讨论】:

  • 感谢您的提示。但我使用警报只是为了让页面出现一些延迟。否则,问题就不会发生。让我看看我是否可以通过其他方式触发问题。
  • @avanc 问题是警报在 Firefox 中破坏了 Angular 的摘要。而这种方法可以防止它发生。我完全不明白你想要达到什么目的。如果你只想延迟它,那么你可以使用 $timeout。
  • 仍然是相同的行为(有时运行,有时不运行):jsfiddle.net/cwesM/5
  • 不要使用基于 $$phase 的安全应用([相关讨论在这里](stackoverflow.com/questions/12729122/…)),因为 $$ 意味着它不是未来安全的,并且未来版本的 Angular 将可能会破坏您的代码:(如果需要,您可以使用 $timeout 进行安全应用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多