Застрял с бесконечно повторяющимися циклами дайджеста
У меня есть Angular SPA, на котором я работаю с Angular Loading Bar и AngularJS v1.4.9.
В течение некоторого времени это происходило так, что после загрузки приложения панель застревала через некоторое время, указывая, что не все запросы выполняются. Кроме того, один из console.log()
s Я в нашем коде стрелял непрерывно, примерно 1-2 раза в секунду. Панель завершается, и console.log работает нормально, когда пользователь перезагружает страницу (но не останавливается самостоятельно).
console.log()
устанавливается внутри функции, прикрепленной к ng-disabled
директива, так что я знаю, что это индикатор выполнения цикла дайджеста.
Я использую Chrome в качестве браузера и недавно выполнил профилирование. Вот несколько скриншотов того, что я вижу:
Это широкий взгляд. Как показано здесь, сначала это происходит в 100 мс, затем в 400, затем в 600 и т. Д. (Я выполнил 3 с).
Это самая первая вертикальная полоса. Не все из них выглядят точно так же, как этот, но методы completeOutstandingRequest, timeout и Browser.self.defer всегда присутствуют. Методы searchDisable и log - наши, журнал - тот, о котором я говорил выше.
Вот еще один для сравнения, но это немного отличается - у него есть другой метод браузера: self.url. Я не уверен, что это делает.
Вот некоторые проблемы, которые я нашел, которые могут быть связаны:
Обратный вызов тайм-аута может происходить в середине цикла дайджеста в Firefox
$ browser.defer заканчивает тем, что запускает changeDetection в zonejs через settimeout
PS Я думаю, что эта проблема впервые возникла, когда мы добавили несколько перехватчиков в наш код для выполнения некоторых автоматических перенаправлений - например, когда время сеанса истекло, и пользователь что-то нажимает, он автоматически возвращается на страницу входа для повторной регистрации.
Это перехватчик:
interceptor.$inject = ['$rootScope', '$q'];
function interceptor($rootScope, $q) {
return {
responseError: function (rejection) {
var config = rejection.config || {};
if (!config.ignoreAuthModule) {
switch (rejection.status) {
case 401:
var deferred = $q.defer();
$rootScope.$broadcast('event:auth-loginRequired', rejection);
return deferred.promise;
case 403:
$rootScope.$broadcast('event:auth-forbidden', rejection);
break;
}
}
return $q.reject(rejection);
}
};
}
$httpProvider.interceptors.push(interceptor);
1 ответ
Эта проблема была решена.
Оказывается, что в случае любого Unauthorized
запросы, обещание, которое возвращается в строке 11 выше, оставалось в ожидании навсегда, потому что не было вызова .resolve()
или же .reject()
в deferred
объект.
В результате перехватчик загрузочного бруса был заблокирован.
Я полностью удалил пользовательское обещание, и это решило проблему.