$应用已在进行中的错误

堆栈跟踪:

Error: $apply already in progress
at Error (<anonymous>)
at beginPhase (file:///android_asset/www/built.min.js:7:22740)
at Object.Scope.$apply (file:///android_asset/www/built.min.js:7:25967)
at navigator.geolocation.getCurrentPosition.that (file:///android_asset/www/built.min.js:13:8670)
at Object.geolocation.getCurrentPosition (file:///android_asset/www/plugins/org.apache.cordova.core.geolocation/www/geolocation.js:122:13)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8589)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8277)
at Object.getCurrentCity (file:///android_asset/www/built.min.js:13:8941)
at Object.$scope.locateDevice (file:///android_asset/www/built.min.js:13:10480)
at file:///android_asset/www/built.min.js:7:12292:7

指的是这个代码 http://pastebin.com/B9V6yvFu

    getCurrentPosition: cordovaReady(function (onSuccess, onError, options) {


navigator.geolocation.getCurrentPosition(function () {
var that = this,
args = arguments;


if (onSuccess) {
$rootScope.$apply(function () {
onSuccess.apply(that, args);
});
}
}, function () {
var that = this,
args = arguments;
if (onError) {
$rootScope.$apply(function () {
onError.apply(that, args);
});
}
}, {
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 18000000
});
})

奇怪的是,在我的 LG4X 上它工作得很好,但是在我的三星 s2上它抛出了上面的错误。知道是什么问题吗?

183567 次浏览

之所以出现这个错误,是因为您在现有的消化周期内调用 $apply

最大的问题是: 你为什么打电话给 $apply?你应该永远不需要调用 $apply,除非你是从一个非角事件接口。$apply的存在通常意味着我正在做一些错误的事情(除非 $application 发生在非角事件中)。

如果 $apply真的适合这里,考虑使用“安全应用”方法:

Https://coderwall.com/p/ngisma

如果在某些情况下必须应用范围,那么您可以设置一个超时,这样 $application 将延迟到下一个刻度

setTimeout(function(){ scope.$apply(); });

或者将代码包装在 $timeout (function (){中。. }); 因为它将在执行结束时自动应用作用域。如果你需要你的函数同步运行,我会做第一个。

你可以这样说:

if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') {
$scope.$apply();
}

刚刚解决了这个问题。它的文件 给你

我在同一个流程中两次调用 $rootScope.$apply。我所做的就是用 setTimeout(func, 1)包装服务函数的内容。

在任何时间点,只能有一个 $digest$apply操作在进行中。这是为了防止很难检测到进入应用程序的错误。此错误的堆栈跟踪允许您跟踪当前正在执行的 $apply$digest调用的原点,该调用导致了此错误。

更多信息: Https://docs.angularjs.org/error/$rootscope/inprog?p0=$apply

只要使用 $evalAsync而不是 $apply

在角度1.3,我认为,他们增加了一个新的功能-$scope.$applyAsync()。这个函数调用将在以后应用——它们说至少要晚10毫秒。它并不完美,但至少消除了恼人的错误。

Https://docs.angularjs.org/api/ng/type/ $rootScope

在我的例子中,我使用 $apply和角度日历 UI 来链接一些事件:

$scope.eventClick = function(event){
$scope.$apply( function() {
$location.path('/event/' + event.id);
});
};

在阅读问题的文档之后: https://docs.angularjs.org/error/ $rootScope/inprog

不一致的 API (同步/异步)部分非常有趣:

例如,假设一个第三方库有一个方法可以为我们检索数据。由于它可能对服务器进行异步调用,因此它接受一个回调函数,当数据到达时将调用该函数。

因为 MyController 构造函数总是从 $application 调用中实例化,所以我们的处理程序试图从一个调用中输入一个新的 $application 块。

我把密码改成:

$scope.eventClick = function(event){
$timeout(function() {
$location.path('/event/' + event.id);
}, 0);
};

非常有效!

在这里,我们使用 $timeout 来安排对未来调用堆栈中的作用域的更改。通过提供0ms 的超时时间,这将尽快发生,并且 $timeout 将确保代码将在单个 $Apply 块中调用。

我调用 $scope. $像这样应用于一次忽略多个调用。

      var callApplyTimeout = null;
function callApply(callback) {
if (!callback) callback = function () { };
if (callApplyTimeout) $timeout.cancel(callApplyTimeout);


callApplyTimeout = $timeout(function () {
callback();
$scope.$apply();
var d = new Date();
var m = d.getMilliseconds();
console.log('$scope.$apply(); call ' + d.toString() + ' ' + m);
}, 300);
}

打个电话就行

callApply();

我知道这是个老问题,但是如果您真的需要使用 $scope

在这种情况下,我们可以使用 setTimeout函数。

console.log('primary task');


setTimeout(function() {
  

console.log('secondary task');


}, 0);


这将确保在完成主任务时执行辅助任务。

只有在 $apply尚未进行的情况下,才可以更改 $apply。您可以将代码更新为

if(!$scope.$$phase) $scope.$apply();