Ошибка: $rootScope:inprog - Как правильно "не" выполнить $apply в angular?

AngularJS Wiki - Anti-Patterns заявляет следующее:

Не делай if (!$scope.$$phase) $scope.$apply(), это означает, что ваш $scope.$apply() недостаточно высоко в стеке вызовов.

И я вроде понимаю это. Существует встроенная логика, которая определяет, когда что должно быть выполнено. И когда внешний разработчик, без непосредственного указания на выполнение во время выполнения различных процедур, определяет, что и где должно выполняться, он противодействует платформе.

Но в настоящее время я загружаю большой файл, в котором процесс загрузки отображается через индикатор выполнения. Библиотека, которую я использую (resumableJS), в свою очередь, имеет событие fileProgress, которое вызывается во время загрузки. Если я ничего не делаю во время этого события, панель не обновляется. Если я поставлю $scope.$apply() там бар обновляется соответственно, но я получаю дайджест и / или применяю уже выполняющуюся ошибку. Наконец, с помощью $$phase проверьте, что я получаю лучшее из обоих миров, обновленный индикатор выполнения без каких-либо ошибок.

Итак, какова правильная альтернатива для обновления моего бара, не влияя на порядок обработки углов?

2 ответа

Решение

В вашем случае вы пытаетесь запустить цикл дайджеста, когда цикл дайджеста уже находится в фазе. Так что выкидывает ошибку

Вы можете использовать что-то вроде setTimeout(fn,0). По сути, он сразу добавляет новое сообщение в очередь и будет обработан после завершения выполняющегося в данный момент кода.

Так что в вашем угловом коде, где вы явно выполняете свой $scope.$ Apply(), измените его на код ниже, и он должен работать.

$timeout(function(){
   $scope.$apply();
},0)

Ошибка: $rootScope:inprog Действие уже в процессе

В любой момент времени может быть только один $digest или же $apply Операция в процессе. Это сделано для того, чтобы очень трудно обнаружить ошибки, попадающие в ваше приложение. Трассировка стека этой ошибки позволяет проследить происхождение выполняющегося в данный момент $apply или же $digest вызов, вызвавший ошибку.

Общие причины

Помимо просто неправильных звонков $apply или же $digest В некоторых случаях вы можете получить эту ошибку не по своей вине.

Несогласованный API (синхронизация / асинхронность)

Эта ошибка часто наблюдается при взаимодействии с API, который иногда синхронизируется, а иногда асинхронен.

Это не идеальный выбор дизайна со стороны сторонней библиотеки.

Чтобы решить проблему такого типа, либо исправьте API-интерфейс, чтобы он всегда был синхронным, либо асинхронным, либо заставьте обработчик обратного вызова всегда работать асинхронно, используя $timeout оказание услуг.

function MyController($scope, $timeout, thirdPartyComponent) {
  thirdPartyComponent.getData(function(someData) {
    $timeout(function() {
      $scope.someData = someData;
    }, 0);
  });
}

Здесь мы использовали $timeout запланировать изменения в области в будущем стеке вызовов. Предоставляя период ожидания 0 мс, это произойдет как можно скорее и $timeout будет гарантировать, что код будет вызываться в одном $apply блок.

** Используйте эту технику только в крайнем случае **.

Лучше всего найти источник ошибки и исправить ее.

Для получения дополнительной информации см. Справочник по ошибкам AngularJS - $ rootScope / inprog - Диагностика этой ошибки

Смотрите также,

Другие вопросы по тегам