【问题标题】:Getting AngularJS Error: "[$rootScope:inprog] $digest already in progress" without a manual $apply获取 AngularJS 错误:“[$rootScope:inprog] $digest 已经在进行中”没有手动 $apply
【发布时间】:2014-03-18 12:08:17
【问题描述】:

关于此错误的其他帖子总是包含有人试图 $apply 而不使用安全应用,但在我的示例中并非如此。我的函数成功返回了我从 API 请求的数据,但我无法清除这个错误,这让我抓狂。 每次在 $http 函数中调用 .success 之前,我都会在控制台中收到“错误:[$rootScope:inprog] $digest already in progress”。以下是我的控制器和服务。谢谢!

这是我的服务,包括一个使用有效负载发布 $http 调用的函数:

Services.service( 'CoolService', ['$q', '$rootScope', '$http', 'Auth', function($q, $rootScope, $http, Auth){
var service = {
    create: function(payload){
        var deferred = $q.defer();
        $http({
            'url': '/api/endpoint/',
            'dataType':'json',
            'method': 'POST',
            data: payload
        }).success(function(data,status, headers, config){
            deferred.resolve(data);

        })
        .error(function(data, status, headers, config){
            deferred.reject("Error in request.");
        });
        return deferred.promise;
        }
    }
    return service;
}]);

这是调用服务的控制器:

controllers.controller('CoolCtrl',['$scope', '$modal', '$log','CoolService', function($scope, $modal, $log, CoolService){
    getCoolData = function (input_data) {
        CoolService.create(input_data).then(function(results){
            new_cool = results.results;
        }, function(error){
        console.log("there was an error getting new cool data");
        });
    };
    var payload = {
        user_id: data1,
        cool_id: data2,
    }
    var new_cool_data = getCoolData(payload);
    console.log(new_cool_data);
}]);

var new_cool_data 下面的日志在异步操作之前被调用,但 new_cool 确实在 getCoolData 内的 .then 语句中分配。 任何帮助摆脱此错误或使其总体上不那么糟糕的帮助将不胜感激!

这是整个错误: https://gist.github.com/thedore17/bcac9aec781ef9ba535b

【问题讨论】:

  • 你还有错误之前的堆栈跟踪吗?
  • 您的错误发生在 ui-bootstrap,而不是您的服务中:(匿名函数)ui-bootstrap-tpls-0.10.0.js:1539
  • 这解释了很多,谢谢。我能做些什么吗?从技术上讲,一切正常,但我觉得出现这个错误并不好。
  • 嗯,它是开源的,因此您可以随时深入研究 ui-bootstrap 库。 :) 或者在他们的网站上打开一个问题。

标签: angularjs angularjs-service angularjs-controller angularjs-http


【解决方案1】:

添加这个小方法并在apply()的地方调用它

function CheckScopeBeforeApply() {
    if(!$scope.$$phase) {
         $scope.$apply();
    }
};

【讨论】:

  • 是的,这是反模式。请参阅下面的答案以获取替代方法。
【解决方案2】:

这为我解决了这个问题。只需添加一次,您无需再更改代码:

https://github.com/angular/angular.js/issues/10083#issuecomment-145967719

.config(function($provide) {
  // Workaround for https://github.com/angular/angular.js/issues/10083
  $provide.decorator('$rootScope', ['$delegate', '$exceptionHandler',
    function($delegate, $exceptionHandler) {
      var proto = Object.getPrototypeOf($delegate);
      var originalDigest = proto.$digest, originalApply = proto.$apply;
      proto.$digest = function() {
        if ($delegate.$$phase === '$digest' || $delegate.$$phase === '$apply') return;
        originalDigest.call(this);
      };
      proto.$apply = function(fn) {
        if ($delegate.$$phase === '$digest' || $delegate.$$phase === '$apply') {
          try {
            this.$eval(fn);
          } catch(e) {
            $exceptionHandler(e);
          }
        } else {
          originalApply.call(this, fn);
        }
      };
      return $delegate;
    }
  ]);
})

【讨论】:

    【解决方案3】:

    我使用了替代解决方案,像这样将 $scope.$apply() 置于超时状态,它起作用了...

    setTimeout(function(){
      $scope.$apply();
    },1);
    

    我认为这只是因为 Angular 的应用生命周期已经在运行,而我的手动 $apply 中断了它。

    【讨论】:

    • 你也可以对 $digest() 使用同样的方法。
    【解决方案4】:

    有一个更简单的解决方案:

    $scope.$evalAsync(function() {
        // Code here
    });
    

    或者简单地说:

    $scope.$evalAsync();
    

    这避免了由 $scope.$apply() 引起的问题,尽管应该注意它不会立即运行(这是您不会收到 inprog 错误的部分原因)。我使用它而不是 $scope.$apply(),它为我省去了很多麻烦。

    请参阅:https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$evalAsync

    【讨论】:

      猜你喜欢
      • 2014-10-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      • 2015-04-08
      • 1970-01-01
      • 2013-01-28
      • 1970-01-01
      相关资源
      最近更新 更多