我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。
我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:
错误:$digest已在进行中
有人知道如何避免这种错误或以不同的方式实现相同的事情吗?
当前回答
摘要周期是一个同步调用。在完成之前,它不会将控制权交给浏览器的事件循环。有几种方法可以解决这个问题。处理此问题的最简单方法是使用内置的$timeout,第二种方法是如果您使用下划线或lodash(您应该使用),请调用以下命令:
$timeout(function(){
//any code in here will automatically have an apply run afterwards
});
或者如果你有lodash:
_.defer(function(){$scope.$apply();});
我们尝试了几种变通方法,我们讨厌将$rootScope注入所有控制器、指令,甚至一些工厂。因此,到目前为止,$timeout和_.defer一直是我们的最爱。这些方法成功地告诉angular等待下一个动画循环,这将保证当前范围$申请已结束。
其他回答
尝试使用
$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文件
在为我们创建一个可重用的$safeApply函数方面,yearmomo做得很好:
https://github.com/yearofmoo/AngularJS-Scope.SafeApply
用法:
//use by itself
$scope.$safeApply();
//tell it which scope to update
$scope.$safeApply($scope);
$scope.$safeApply($anotherScope);
//pass in an update function that gets called when the digest is going on...
$scope.$safeApply(function() {
});
//pass in both a scope and a function
$scope.$safeApply($anotherScope,function() {
});
//call it on the rootScope
$rootScope.$safeApply();
$rootScope.$safeApply($rootScope);
$rootScope.$safeApply($scope);
$rootScope.$safeApply($scope, fn);
$rootScope.$safeApply(fn);
保持此过程干燥的简便小助手方法:
function safeApply(scope, fn) {
(scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}
类似于上面的答案,但这对我来说非常有效。。。在服务中添加:
//sometimes you need to refresh scope, use this to prevent conflict
this.applyAsNeeded = function (scope) {
if (!scope.$$phase) {
scope.$apply();
}
};
这是我的utils服务:
angular.module('myApp', []).service('Utils', function Utils($timeout) {
var Super = this;
this.doWhenReady = function(scope, callback, args) {
if(!scope.$$phase) {
if (args instanceof Array)
callback.apply(scope, Array.prototype.slice.call(args))
else
callback();
}
else {
$timeout(function() {
Super.doWhenReady(scope, callback, args);
}, 250);
}
};
});
这是它的用法示例:
angular.module('myApp').controller('MyCtrl', function ($scope, Utils) {
$scope.foo = function() {
// some code here . . .
};
Utils.doWhenReady($scope, $scope.foo);
$scope.fooWithParams = function(p1, p2) {
// some code here . . .
};
Utils.doWhenReady($scope, $scope.fooWithParams, ['value1', 'value2']);
};