为什么使用 if(!$scope.$$phase) $scope.$apply() 反模式? [英] Why is using if(!$scope.$$phase) $scope.$apply() an anti-pattern?

查看:22
本文介绍了为什么使用 if(!$scope.$$phase) $scope.$apply() 反模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时我需要在我的代码中使用 $scope.$apply ,有时它会抛出摘要已经在进行中"错误.所以我开始想办法解决这个问题,发现了这个问题:AngularJS :在调用 $scope.$apply() 时防止错误 $digest 已经在进行中.但是,在评论(以及 angular wiki)中,您可以阅读:

Sometimes I need to use $scope.$apply in my code and sometimes it throws a "digest already in progress" error. So I started to find a way around this and found this question: AngularJS : Prevent error $digest already in progress when calling $scope.$apply(). However in the comments (and on the angular wiki) you can read:

不要做 if (!$scope.$$phase) $scope.$apply(),这意味着你的 $scope.$apply() 在调用堆栈中不够高.

Don't do if (!$scope.$$phase) $scope.$apply(), it means your $scope.$apply() isn't high enough in the call stack.

所以现在我有两个问题:

So now i have two questions:

  1. 为什么这是一种反模式?
  2. 如何安全地使用 $scope.$apply?

防止消化已经在进行中"错误的另一个解决方案"似乎是使用 $timeout:

Another "solution" to prevent "digest already in progress" error seems to be using $timeout:

$timeout(function() {
  //...
});

这是要走的路吗?更安全吗?所以真正的问题是:我如何完全消除正在消化"错误的可能性?

Is that the way to go? Is it safer? So here is the real question: How I can entirely eliminate the possibility of a "digest already in progress" error?

PS:我只在非同步的非 angularjs 回调中使用 $scope.$apply.(据我所知,如果您希望应用更改,则必须使用 $scope.$apply 的情况)

PS: I am only using $scope.$apply in non-angularjs callbacks that are not synchronous. (as far as I know those are situations where you must use $scope.$apply if you want your changes to be applied)

推荐答案

经过更多的挖掘,我能够解决使用 $scope.$apply 是否总是安全的问题.简短的回答是肯定的.

After some more digging i was able to solve the question whether it's always safe to use $scope.$apply. The short answer is yes.

长答案:

由于您的浏览器执行 Javascript 的方式,两个摘要调用不可能偶然发生冲突.

Due to how your browser executes Javascript, it is not possible that two digest calls collide by chance.

我们编写的 JavaScript 代码不是一次性运行的,而是轮流执行的.这些转弯中的每一个都从头到尾不间断地运行,当转弯运行时,我们的浏览器中不会发生任何其他事情.(来自 http://jimhoskins.com/2012/12/17/angularjs-and-apply.html)

The JavaScript code we write doesn’t all run in one go, instead it executes in turns. Each of these turns runs uninterupted from start to finish, and when a turn is running, nothing else happens in our browser. (from http://jimhoskins.com/2012/12/17/angularjs-and-apply.html)

因此错误digest already in progress"只会在一种情况下发生:当 $apply 在另一个 $apply 内发出时,例如:

Hence the error "digest already in progress" can only occur in one situation: When an $apply is issued inside another $apply, e.g.:

$scope.apply(function() {
  // some code...
  $scope.apply(function() { ... });
});

这种情况不会出现如果我们在纯非angularjs回调中使用$scope.apply,例如setTimeout.所以下面的代码是 100% 防弹的,并且不需要需要做一个 if (!$scope.$$phase) $scope.$apply()

This situation can not arise if we use $scope.apply in a pure non-angularjs callback, like for example the callback of setTimeout. So the following code is 100% bulletproof and there is no need to do a if (!$scope.$$phase) $scope.$apply()

setTimeout(function () {
    $scope.$apply(function () {
        $scope.message = "Timeout called!";
    });
}, 2000);

即使是这个也是安全的:

even this one is safe:

$scope.$apply(function () {
    setTimeout(function () {
        $scope.$apply(function () {
            $scope.message = "Timeout called!";
        });
    }, 2000);
});

什么是安全的(因为 $timeout - 就像所有 angularjs 助手一样 - 已经为你调用了 $scope.$apply):

What is NOT safe (because $timeout - like all angularjs helpers - already calls $scope.$apply for you):

$timeout(function () {
    $scope.$apply(function () {
        $scope.message = "Timeout called!";
    });
}, 2000);

这也解释了为什么 if (!$scope.$$phase) $scope.$apply() 的用法是一种反模式.如果您以正确的方式使用 $scope.$apply ,则根本不需要它:例如,在像 setTimeout 这样的纯 js 回调中.

This also explains why the usage of if (!$scope.$$phase) $scope.$apply() is an anti-pattern. You simply don't need it if you use $scope.$apply in the correct way: In a pure js callback like setTimeout for example.

阅读http://jimhoskins.com/2012/12/17/angularjs-and-apply.html 以获得更详细的解释.

Read http://jimhoskins.com/2012/12/17/angularjs-and-apply.html for the more detailed explanation.

这篇关于为什么使用 if(!$scope.$$phase) $scope.$apply() 反模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆