我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
当前回答
let $timeoutPromise = null;
$timeout.cancel($timeoutPromise);
$timeoutPromise = $timeout(() => {
$scope.$digest();
}, 0, false);
以下是避免此错误和避免$apply的好解决方案
如果基于外部事件调用,则可以将其与反跳(0)结合使用。以上是我们正在使用的“反跳”,以及完整的代码示例
.factory('debounce', [
'$timeout',
function ($timeout) {
return function (func, wait, apply) {
// apply default is true for $timeout
if (apply !== false) {
apply = true;
}
var promise;
return function () {
var cntx = this,
args = arguments;
$timeout.cancel(promise);
promise = $timeout(function () {
return func.apply(cntx, args);
}, wait, apply);
return promise;
};
};
}
])
以及代码本身,以侦听某些事件并仅在需要的$scope上调用$digest
let $timeoutPromise = null;
let $update = debounce(function () {
$timeout.cancel($timeoutPromise);
$timeoutPromise = $timeout(() => {
$scope.$digest();
}, 0, false);
}, 0, false);
let $unwatchModelChanges = $scope.$root.$on('updatePropertiesInspector', function () {
$update();
});
$scope.$on('$destroy', () => {
$timeout.cancel($update);
$timeout.cancel($timeoutPromise);
$unwatchModelChanges();
});
其他回答
当您收到此错误时,基本上意味着它已经在更新视图的过程中。您真的不需要在控制器中调用$apply()。如果您的视图没有按预期进行更新,并且在调用$apply()后出现此错误,那么很可能意味着您没有正确更新模型。如果你发布一些细节,我们可以找出核心问题。
当我们要求angular运行摘要循环时,问题基本上就要出现了,尽管它正在进行中,这对angular的理解造成了问题。控制台中的结果异常。1.调用范围没有任何意义$$timeout函数中的apply(),因为在内部它也会这样做。2.该代码使用普通JavaScript函数,因为它的本机非角度定义,即setTimeout3.要做到这一点,你可以利用if(!scope.$$phase){范围$evalAsync(函数){});}
首先,不要这样解决
if ( ! $scope.$$phase) {
$scope.$apply();
}
它没有意义,因为$phase只是$digest循环的布尔标志,所以$apply()有时无法运行。记住这是一种糟糕的做法。
而是使用$timeout
$timeout(function(){
// Any code in here will automatically have an $scope.apply() run afterwards
$scope.myvar = newValue;
// And it just works!
});
如果使用下划线或lodash,可以使用defer():
_.defer(function(){
$scope.$apply();
});
我一直在使用这种方法,它似乎工作得很好。这只是等待循环完成的时间,然后触发apply()。只需从任意位置调用函数apply(<yourscope>)。
function apply(scope) {
if (!scope.$$phase && !scope.$root.$$phase) {
scope.$apply();
console.log("Scope Apply Done !!");
}
else {
console.log("Scheduling Apply after 200ms digest cycle already in progress");
setTimeout(function() {
apply(scope)
}, 200);
}
}
如果你这样做,有时你仍然会出错(https://stackoverflow.com/a/12859093/801426).
试试看:
if(! $rootScope.$root.$$phase) {
...