简体   繁体   English

调试$ digest已在进行中错误

[英]Debugging $digest already in progress error

I'm building a complex hybrid app and have been testing on a real device. 我正在构建一个复杂的混合应用程序并且已经在真实设备上进行测试。 Occasionally, I'm getting the dreaded $digest already in progress error from Angular - especially, it appears to be after a somewhat long digest cycle. 偶尔,我从Angular那里得到了可怕的$digest already in progress错误 - 特别是,它似乎是在一个有点长的摘要周期之后。 From the stack trace it appears to be initiated from an Angular defer function that updates the location.href, which then triggers fastclick to send a touchend that in turn triggers a second digest leading to the error. 从堆栈跟踪看来,它似乎是从更新location.href的Angular defer函数启动的,然后触发fastclick以发送touchend,而touchend又触发导致错误的第二个摘要。 Has anyone experienced this same error - and if so, how did you go about resolving it? 有没有人遇到过同样的错误 - 如果有的话,你是怎么解决它的?

For those interested, here is what I am seeing in the stacktrace: 对于那些感兴趣的人,这是我在stacktrace中看到的:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.0/$rootScope/inprog?p0=%24digest:
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:80:32
beginPhase@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14473:31
$apply@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14220:21
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:22523:29
eventHandler@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:3013:25
dispatchEvent@sendClick@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/fastclick/fastclick.js:295:30
onTouchEnd@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/fastclick/fastclick.js:589:18
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/fastclick/fastclick.js:105:43
url@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:5022:19
setBrowserUrlWithFallback@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:11080:21
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:11186:40
$eval@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14123:28
$digest@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:13939:36
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14161:33
completeOutstandingRequest@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:4877:15
file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:5250:33

Here's the havoc wreaker ( source link ): 这是破坏者的破坏者( 来源链接 ):

FastClick.prototype.sendClick = function(targetElement, event) {
    // ... some lines skipped

    clickEvent = document.createEvent('MouseEvents');
    clickEvent.forwardedTouchEvent = true;
    targetElement.dispatchEvent(clickEvent); // got you!
};

The problem is that the handler for the artificial click will be fired immediately ( demo ). 问题是人工click的处理程序将立即被触发( 演示 )。 That's usually fine - but not with Angular, because touchEnd event has been generated within $digest phase, and ng-click seems to be somewhat optimistic about events it has to process with its $apply code. 这通常很好 - 但不适用于Angular,因为touchEnd事件已在$digest阶段生成,而ng-click似乎对它必须使用$apply代码处理的事件感到有些乐观。 Hence the $digest ka-boom. 因此, $digest ka-boom。

Anyway, this thing seems to be pretty fixable: just async the event dispatch! 无论如何,这件事似乎很容易解决:只是异步事件发送! One, rather straightforward way is replacing the got you! 一个相当简单的方法就是取代got you! line with something like... 与...类似的行

setTimeout(function() {
  targetElement.dispatchEvent(clickEvent);
}, 0);

Seems to work in our case, at least. 似乎至少在我们的案例中起作用。 )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM