【问题标题】:$digest already in progress - Directive in AngularJS$digest 已经在进行中 - AngularJS 中的指令
【发布时间】:2013-08-19 14:54:11
【问题描述】:

我目前收到常见的“$digest already in progress”错误消息。

是否有不需要使用 scope.$apply 的解决方案?

感谢您的帮助!

directive('ngUsername', ['$http', function($http) {
return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elm, attr, ctrl) {
        //when the scope changes, check the email.
        scope.$watch(attr.ngModel, function(value) {
            $http.get('http://tagsy.co/api/username?token=' + apiToken + '&username=' + value).success(function(data) {
                scope.$apply(function(s) {
                    ctrl.$setValidity('uniqueUsername', data.unique);
                });
            });
        });
    }
}
}]);

<input type="text" name="username" ng-model="username" placeholder="Username" ng-minlength="3" ng-maxlength="15" ng-pattern="/^[A-Za-z0-9]+$/" autocomplete="off" ng-username required/>

<div ng-show="registerForm.username.$dirty && registerForm.username.$invalid">
    <span class="error" ng-show="registerForm.username.$error.required">Please choose a username.</span>
    <span class="error" ng-show="registerForm.username.$error.minlength">Username is too short.</span>
    <span class="error" ng-show="registerForm.username.$error.maxlength">Username is too long.</span>
    <span class="error" ng-show="registerForm.username.$error.pattern">Username can only be letters and numbers.</span>
    <span class="error" ng-show="registerForm.username.$error.uniqueUsername">Username is already taken.</span>
</div>

【问题讨论】:

  • 你能详细说明你想要什么吗?从代码中扣除$http.get()返回的内容并不容易
  • 在调用$http 服务后,您不需要$apply
  • @sza 由于 $http 是异步的,它在 $watch 中被调用的事实并不能保证在完成和success 回调的时间之后循环将在进行中。真的要靠 $http 服务来触发循环。
  • 谢谢。那么如果我不需要使用scope.$apply,我该如何设置validity选项呢?

标签: javascript ajax angularjs


【解决方案1】:

在手动开始循环之前,您可以使用$scope.$$phase 检查它是否正在进行中。当$scope.$$phase没有设置时,使用$apply是安全的:

scope.$watch(attr.ngModel, function(value) {
  $http.get('http://tagsy.co/api/username?token=' + apiToken + '&username=' + value).success(function(data) {
    if(!scope.$$phase)
        scope.$apply(function(s) {
                ctrl.$setValidity('uniqueUsername', data.unique);
        });
    else
      ctrl.$setValidity('uniqueUsername', data.unique);
  });
}

您可以重构以避免代码冗余或创建一个帮助程序,例如:

function safeApply($scope, applyFn) {
    if(!$scope.$$phase) $scope.$apply(applyFn)
    else applyFn();
}

scope.$watch(attr.ngModel, function(value) {
  $http.get('http://tagsy.co/api/username?token=' + apiToken + '&username=' + value).success(function(data) {
    safeApply(scope, function() {
      ctrl.$setValidity('uniqueUsername', data.unique);
    });
  });
}

编辑:这并不是说你应该在这种情况下这样做,因为 $http(和大多数 Angular 服务)会为你处理好。

【讨论】:

  • 您好,谢谢。我已经尝试过这个解决方案,但没有任何错误消息显示?
  • 永远不要使用 $$phase 进行检测 (previous post about this topic here),因为它对未来不安全,更高版本的 Angular 会破坏您的代码:(
  • @betaorbust 很高兴知道,关于未来版本,我不知道 $$phase 的状态。
【解决方案2】:

当您调用 $http.[verb] 时,响应(成功或错误)将执行,然后 $rootScope.$digest() 将被执行。您不需要在此方法中执行 $scope.$apply。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-12
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多