获取 AngularJS 错误:“[$rootScope:inprog] $digest 已经在进行中”没有手动 $apply

Posted

技术标签:

【中文标题】获取 AngularJS 错误:“[$rootScope:inprog] $digest 已经在进行中”没有手动 $apply【英文标题】:Getting AngularJS Error: "[$rootScope:inprog] $digest already in progress" without a manual $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

【问题讨论】:

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

【讨论】:

以上是关于获取 AngularJS 错误:“[$rootScope:inprog] $digest 已经在进行中”没有手动 $apply的主要内容,如果未能解决你的问题,请参考以下文章

(转) angularJS的controller之间如何正确的通信

如何在AngularJS中的两个控制器之间广播事件

离子应用程序 iOS 9 问题 [$rootScope:infdig] 10 $digest() 迭代达到 [重复]

Angular 混合错误:试图在设置之前获取 AngularJS 注入器

如何从 angularjs 中的 JSONP 错误回调中获取数据?

获取 AngularJS 错误:“[$rootScope:inprog] $digest 已经在进行中”没有手动 $apply