0

我目前收到常见的“$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>
4

2 回答 2

1

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

于 2013-12-11T01:06:03.080 回答
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 服务)会为你解决这个问题。

于 2013-08-19T14:56:49.753 回答