Ошибка: $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 - Диагностика этой ошибки
Смотрите также,