Нужно ли отменять тайм-аут AngularJS $http?
Я пытаюсь улучшить производительность своего приложения на мобильных устройствах с медленными сетями.
Первым шагом было добавление "глобального" таймаута для всех http-запросов, я использовал простой request
перехватчик для этого - request(config) { return angular.extend({ timeout: 30000 }, config) }
, Это работало нормально - вместо бесконечного ожидания ответа я мог отобразить предупреждение о медленной сети (в responseError
interceptor), более того, медленный запрос отменяется, поэтому я могу ожидать, что он освободит некоторую полосу пропускания для других запросов.
Сейчас я пытаюсь реализовать еще одну оптимизацию - отмена ожидающих http-запросов до изменения состояния uiRouter, поскольку нет причин загружать ресурсы для состояния, которое больше не будет отображаться. Например, случай, когда пользователь пытается перейти в состояние A, ожидаемые разрешения A ожидают, скучающий пользователь передумал и пытается перейти в состояние B.
Моя текущая реализация основана на $q
а также $timeout
услуги и пользовательский сервис для сбора тайм-аутов для всех http-запросов и отмены их в пакете при необходимости. Достаточно слов, вот код:
const REQUEST_TIMEOUT = 3000; // 30 secs
function httpRequestsCancellerService($timeout, $transitions, $q) {
const cancelers = [];
function cancelAll() {
while (cancelers.length > 0) {
const canceler = cancelers.pop();
canceler.resolve();
}
}
// Cancel all pending http requests before the next transition
$transitions.onStart({}, cancelAll);
return {
createTimeout() {
const canceler = $q.defer();
// TODO it will keep running even whe the request is completed or failed
$timeout(canceler.resolve, REQUEST_TIMEOUT);
cancelers.push(canceler);
return canceler.promise;
}
};
}
function timeoutInterceptor(httpRequestsCanceller) {
return {
request(config) {
const timeout = httpRequestsCanceller.createTimeout();
return angular.extend({ timeout }, config);
}
};
}
module.exports = function($httpProvider, $provide) {
'ngInject';
$provide.service('httpRequestsCanceller', httpRequestsCancellerService);
$httpProvider.interceptors.push(timeoutInterceptor);
};
Теперь он отлично работает, но имеет небольшой недостаток - $timeout
в request
перехватчик будет продолжать работать и, наконец, разрешит canceller
даже если запрос завершен или не выполнен.
Вопрос в том, должен ли я заботиться об этих отложенных $timeout
s? Нужно ли $timeout.cancel
их, чтобы освободить некоторые ресурсы или избежать каких-то странных побочных эффектов?