我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
当前回答
您应该根据上下文使用$evalAsync或$timeout。
这是一个有很好解释的链接:
http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm
其他回答
我对第三方脚本也有同样的问题,比如CodeMirror和Krpano,甚至使用这里提到的safeApply方法也没有为我解决错误。
但解决这个问题的方法是使用$timeout服务(不要忘记先注入它)。
因此,类似于:
$timeout(function() {
// run my code safely here
})
如果在代码中使用
这
也许是因为它在工厂指令的控制器内,或者只是需要某种绑定,那么您可以执行以下操作:
.factory('myClass', [
'$timeout',
function($timeout) {
var myClass = function() {};
myClass.prototype.surprise = function() {
// Do something suprising! :D
};
myClass.prototype.beAmazing = function() {
// Here 'this' referes to the current instance of myClass
$timeout(angular.bind(this, function() {
// Run my code safely here and this is not undefined but
// the same as outside of this anonymous function
this.surprise();
}));
}
return new myClass();
}]
)
当我们要求angular运行摘要循环时,问题基本上就要出现了,尽管它正在进行中,这对angular的理解造成了问题。控制台中的结果异常。1.调用范围没有任何意义$$timeout函数中的apply(),因为在内部它也会这样做。2.该代码使用普通JavaScript函数,因为它的本机非角度定义,即setTimeout3.要做到这一点,你可以利用if(!scope.$$phase){范围$evalAsync(函数){});}
尝试使用
$scope.applyAsync(function() {
// your code
});
而不是
if(!$scope.$$phase) {
//$digest or $apply
}
$applysync将$apply的调用安排为稍后进行。这可用于对需要在同一摘要中计算的多个表达式进行排队。
注意:在$digest中,如果当前作用域是$rootScope,则$applySync()将仅刷新。这意味着,如果在子作用域上调用$digest,它将不会隐式刷新$applysync()队列。
Exmaple公司:
$scope.$applyAsync(function () {
if (!authService.authenticated) {
return;
}
if (vm.file !== null) {
loadService.setState(SignWizardStates.SIGN);
} else {
loadService.setState(SignWizardStates.UPLOAD_FILE);
}
});
参考文献:
1.范围.$applySync()与范围$AngularJS 1.3中的evalAsync()
AngularJs文件
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()后出现此错误,那么很可能意味着您没有正确更新模型。如果你发布一些细节,我们可以找出核心问题。