Подтвердить что ты не робот

Ошибка отладки $digest

Я создаю сложное гибридное приложение и тестирую на реальном устройстве. Иногда я получаю страшную ошибку $digest already in progress от Angular - особенно, похоже, после несколько длинного цикла дайджест. Из трассировки стека он, по-видимому, инициируется с помощью функции Angular defer, которая обновляет location.href, которая затем запускает fastclick для отправки touchhend, который, в свою очередь, запускает второй дайджест, приводящий к ошибке. Кто-нибудь испытал такую ​​же ошибку - и если да, то как вы решили ее разрешить?

Для тех, кого это интересует, вот что я вижу в 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
[email protected]:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14473:31
[email protected]:///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
[email protected]:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:3013:25
[email protected]@file:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/fastclick/fastclick.js:295:30
[email protected]:///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
[email protected]:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:5022:19
[email protected]:///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
[email protected]:///private/var/mobile/Containers/Bundle/Application/4040564A-5631-4A1A-B2FD-6E53F9A574F2/test.app/www/js/3rdparty/angular/angular.js:14123:28
[email protected]:///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
[email protected]:///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
4b9b3361

Ответ 1

Здесь havoc wreaker (ссылка источника):

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

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

Проблема заключается в том, что обработчик искусственного click будет немедленно запущен ( demo). Это обычно отлично - но не с Angular, потому что событие touchEnd было сгенерировано в фазе $digest, а ng-click кажется несколько оптимистичным в отношении событий, которые он должен обрабатывать с помощью кода $apply. Следовательно, $digest ka-стрела.

Во всяком случае, эта вещь кажется довольно устрашающей: просто асинхронная отправка событий! Один, довольно простой способ - заменить строку got you! на что-то вроде...

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

Кажется, по крайней мере, работать в нашем случае. )