$digest уже выполняется при вызове $rootScope.$apply() в быстрой последовательности

Поэтому у меня есть служба AngularJS, которая прослушивает некоторые события. При обработке этих событий мне нужно вызывать разные контроллеры и в конечном итоге загружать новое представление. В одном обработчике событий я использую $location.path(), затем вызываю $rootScope.apply() для запуска маршрутизации к контроллеру. Это прекрасно работает для этого события, но в других я получаю следующую ошибку: $rootScope:inprog Action Already In Progress, Я предполагаю, что это работает в первом сценарии, потому что $rootScope.apply() вызывается из другой функции обратного вызова внутри функции слушателя, где другие обработчики пытаются вызвать его только из функции слушателя события.

//angular service

$rootScope.$on('MY_EVENT', function (event, msg) {
    MyClass.doSomething(msg, function (response) {
        $location.path("/view1");
        $rootScope.$apply();        //WORKS FINE
    });
});


$rootScope.$on('MY_OTHER_EVENT', function (event, msg) {
    $location.path("/view2");
    $rootScope.$apply();           //ERROR
});

Как я могу заставить его работать для всех обработчиков событий?

пример plnkr

1 ответ

Решение

Проблема в том, что он выполняет $digest на $rootScope дважды в быстрой последовательности и выдает ошибку, когда есть совпадение. Чтобы обойти это, вы можете просто обернуть оба вызова $location.path() в $timeout, как вы сделали в первый раз в вашем примере plnkr. Это заставит его ждать $digest цикл для завершения.

Вы также можете удалить явные вызовы $rootScope.$apply(),

$rootScope.$on('FIRST_EVENT', function(event, msg) {
  $timeout(function() {
    $location.path("/view1");
  });
});

$rootScope.$on('SECOND_EVENT', function(event, msg) {
  $timeout(function() {
    $location.path("/view2");
  });
});

Замечания:

Этот код основан на примере plnkr, который немного отличается от кода в оригинальном посте.

Ссылка:

дождаться окончания цикла $digest

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