При работе c REST Api со страницы SPA часто возникает необходимость обработки ошибок. Все бы ничего, но часть ответов об ошибках касаются запрашиваемых данных, часть – могут быть ошибками общего вида c которыми тоже надо что-то делать. Предлагаю свое решение данной проблемы.
Для решения проблемы предлагается расширить $q через делегат, добавив к нему методы success, error, defaultError. Eсли error callback в полной мере отработал ошибку, то он должен дернуть preventDefault, иначе будет вызван обработчик ошибки по умолчанию.
vardef=$q.defer();varpromise=def.promise;promise.defaultError(function(error){alert('Error :'+error.description);})promise.success(function(data){// Display new data ...})promise.error(function(error){if(error.type==="wrong_data"){// highlite form fields...this.preventDefault();}})def.reject({type:"unauthed"});// Alarm will be shown// Orelsedef.reject({type:"wrong_data"});// Alarm won't be shown
Теперь сервис $http. Для него лучше всего сделать свою сервис-обертку, к примеру Server. Который и будет задавать обработчик ошибок по-умолчанию
Вот и все… Теперь используем Server взамен $http и обрабатываем только те ошибки, с которыми знаем что делать в данном контексте, об остальных позаботится myDefaultErrorHandler;
12345678910
Server.post('/process',data).success(function(data){// update views}).error(function(error){if(error.type==="wrong_data"){// highlite for fieldsthis.preventDefault();}})
P.S. Можно еще много улучшать этот код: реализовать Server через провайдер, добавить к нему метод setDefaultErrorHandler и т.п…
P.P.S. В angular есть баг связанный с делегатами для $q. Дело в том, что даже если объявить новую функцию для promise в делегатe, при вызове promise.then() вернется объект без нее. Проблема в том, что в коде angular через замыкание всегда используется старая версия функции defer. Я написал PR, но судьба его пока не известна…