我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
当前回答
安全$apply的最短形式是:
$timeout(angular.noop)
其他回答
我建议您使用自定义事件,而不是触发摘要循环。
我发现,广播自定义事件并为此事件注册侦听器是一个很好的解决方案,无论您是否处于摘要周期,都可以触发您希望发生的操作。
通过创建自定义事件,您的代码也会更高效,因为您只触发订阅所述事件的侦听器,而不会像调用作用域时那样触发绑定到作用域的所有监视$申请
$scope.$on('customEventName', function (optionalCustomEventArguments) {
//TODO: Respond to event
});
$scope.$broadcast('customEventName', optionalCustomEventArguments);
当您收到此错误时,基本上意味着它已经在更新视图的过程中。您真的不需要在控制器中调用$apply()。如果您的视图没有按预期进行更新,并且在调用$apply()后出现此错误,那么很可能意味着您没有正确更新模型。如果你发布一些细节,我们可以找出核心问题。
保持此过程干燥的简便小助手方法:
function safeApply(scope, fn) {
(scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}
您可以使用$timeout来防止错误。
$timeout(function () {
var scope = angular.element($("#myController")).scope();
scope.myMethod();
scope.$scope();
}, 1);
我已经能够通过在我知道$digest函数将运行的地方调用$eval而不是$apply来解决这个问题。
根据文档,$apply基本上做到了这一点:
function $apply(expr) {
try {
return $eval(expr);
} catch (e) {
$exceptionHandler(e);
} finally {
$root.$digest();
}
}
在我的例子中,ng单击会更改范围内的变量,而该变量上的$watch会更改必须应用$apply的其他变量。最后一步导致错误“摘要已在进行中”。
通过在watch表达式中将$apply替换为$eval,作用域变量将按预期更新。
因此,如果因为Angular中的一些其他变化,digest将以任何方式运行,那么您需要做的就是$eval‘ing。