AngularJS: 当调用 $scope.$apply() 时,防止出现错误 $digest already in progress。

30 浏览
0 Comments

AngularJS: 当调用 $scope.$apply() 时,防止出现错误 $digest already in progress。

在使用Angular构建应用程序后,我发现越来越需要手动更新我的页面以匹配我的作用域。

我所知道的唯一方法是从我的控制器和指令的作用域调用$apply()。但问题是它会持续向控制台抛出以下错误:

错误:$digest已在进行中

有人知道如何避免这个错误或以不同的方式实现相同的功能吗?

admin 更改状态以发布 2023年5月24日
0
0 Comments

不要使用这个模式 - 这会导致比解决更多的错误。即使你认为它修复了某些问题,其实并没有。

你可以通过检查 $scope.$$phase 来判断是否已经有一个 $digest 正在进行中。

if(!$scope.$$phase) {
  //$digest or $apply
}

$scope.$$phase 如果有一个 $digest$apply 正在进行中,它将返回 "$digest""$apply"。我认为这两种状态之间的区别在于,$digest 将处理当前范围及其子级的观察者,而 $apply 将处理所有作用域的观察者。

关于 @dnc253 的观点,如果你经常调用 $digest$apply,你可能做错了。我通常会发现,当需要更新作用域状态以响应 Angular 之外的 DOM 事件时,我需要进行 digest。例如,当 Twitter Bootstrap 模态框变为隐藏状态时。有时 DOM 事件会在 $digest 进行中触发,有时不会。这就是为什么我使用这个检查。

我很想知道是否有更好的方法,如果有人知道的话。


从评论中得知:by @anddoutoi

AngularJS反模式

  1. 不要这样做 if (!$scope.$$phase) $scope.$apply(),这意味着你的 $scope.$apply() 没有在调用堆栈中的层级足够高。
0
0 Comments

最近与Angular小伙伴们就这个问题进行了讨论:出于未来的保护,你不应该使用$$phase

当被追问什么是“正确”的方法时,目前的答案是

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})

我最近在编写Angular服务以包装Facebook、Google和Twitter API时遇到了这个问题,这些API在不同程度上都有回调函数。

以下是服务中的一个示例。(为了简洁起见,这里省略了其余设置变量、注入$timeout等内容的服务)

window.gapi.client.load('oauth2', 'v2', function() {
    var request = window.gapi.client.oauth2.userinfo.get();
    request.execute(function(response) {
        // This happens outside of angular land, so wrap it in a timeout 
        // with an implied apply and blammo, we're in action.
        $timeout(function() {
            if(typeof(response['error']) !== 'undefined'){
                // If the google api sent us an error, reject the promise.
                deferred.reject(response);
            }else{
                // Resolve the promise with the whole response if ok.
                deferred.resolve(response);
            }
        });
    });
});

请注意,$timeout的延迟参数是可选的,如果未设置,它将默认为0($timeout调用$browser.defer,如果未设置延迟,则默认为0

虽然有点不直观,但这是Angular编写者的答案,所以对我来说已经足够好了!

0