AngularJS: повтор последних запросов при обрыве соединения
Решил сделать кнопку «обновить», которая показывается при обрыве сетевого соединения и повторяет неудавшиеся запросы. Очень актуально для мобильных приложений.
Задача состоит из двух частей:
- Запросы к api на уже сформированной странице (сохранение форм и другие действия без смены контроллера и урла)
- Переход на новый урл (смена через маршрутизацию AngularJS)
Первое у меня сделано через расширение $resource (сделано оно изначально было для другого, но и этот функционал туда вписывается хорошо).
Вкратце идея такова: каждый запрос заносится в объект-хранилище; когда запрос успешно выполняется, он из этого хранилища выбрасывается. Если запрос не был выполнен, то его параметры остаются в хранилище, а в $rootScope ставится флаг, говорящий о том, что произошёл сбой при соединении с api. При этом показывается кнопка «повторить последние запросы», при нажатии на которую сохранённые запросы выполняются заново.
А хотел я остановиться на втором пункте, т.к. реализация не требует расширения библиотеки angular, а реализуется штатными средствами, да к тому же и кода немного.
При смене урла AngularJS сначала делает запрос для загрузки шаблона, и если он не отработал, то выполнение логики контроллера не начинается (кстати, именно поэтому в шаблоне обязательно нужен контент, без него контроллер работать не будет).
Если шаблон не загрузился, то будет сгенерировано событие $routeChangeError. Вешаем обработчик на это событие, который ставит переменную в $rootScope. Для повтора загрузки шаблона и дальнейшего выполнения логики контроллера достаточно выполнить $route.reload();. Так что вот весь код:
app.js
(function ()
{
$rootScope.routeError = false;
$rootScope.$on('$routeChangeError', function (event, current, prev, rejection) {
$rootScope.routeError = true;
});
$rootScope.$on('requests.rerun', function (event, current, prev, rejection) {
if ($rootScope.routeError)
{
$route.reload();
$rootScope.routeError = false;
}
});
}());
$rootScope.rerunRequests = function rerunRequests()
{
$rootScope.$emit('requests.rerun');
};
index.html
<div ng-show="controllerDataLoadError || routeError"> <a href="javascript:;" ng-click="rerunRequests()">Повторить последний запрос</a> </div>
Единственный минус такого подхода
Если вместо callback-ов используются прямое присваивание значения, то повтор запроса не вернет это значение в нужное место. Выход — не использовать такой синтаксис, тем более, что он менее удобен.
Т.е. не надо вместо
MyService.get(params, function (response) {
$scope.response = response;
$scope.$emit('extendedGeoSelector.show');
LoadRendererService.setLoaded();
});
использовать
$scope.response = MyService.get(params);
LEAVE A COMMENT
Для отправки комментария вам необходимо авторизоваться.