У этого есть несколько компонентов, и вам нужно знать о цепочках обещаний, чтобы понять, как все это сочетается друг с другом. Сначала перехватчик
app.factory('RetryInterceptor', function($injector, $timeout, $q) {
return {
'responseError': function(rejection) {
// Avoid circular dependency issues
var Retry = $injector.get('Retry');
var $http = $injector.get('$http');
// Timeout is just to keep UI from changing too quickly
return $timeout(angular.noop,1000).then(function() {
return Retry.show();
}).then(function() {
return $http(rejection.config);
}, function() {
return $q.reject(rejection);
});
}
}
});
зарегистрирован как
app.config(function($httpProvider) {
$httpProvider.interceptors.push('RetryInterceptor');
});
Вышеупомянутый перехватчик responseError возвращает обещание, которое разрешено / отклонено с возвращенным обещанием Retry.open
. Если это обещание будет выполнено, он повторит исходный $http
запрос. Если он отклонен, то ничего не произойдет, кроме обещания, возвращенного при исходном вызове $http
, будет отклонено с тем же объектом отклонения, что и без отображения диалогового окна.
Retry
- это настраиваемая служба, которая предоставляет единственный метод open
. Вы могли бы иметь это в перехватчике, но это сохраняет модульность:
app.service('Retry', function Retry($window, $modal) {
this.show = function() {
return $modal.open({
templateUrl: 'retry-dialog.html',
controller: 'RetryController'
}).result;
}
});
Метод show
возвращает обещание от службы $modal
. Это обещание контролируется объектом $modalInstance
, переданным контроллеру:
app.controller('RetryController', function($scope, $modalInstance) {
$scope.retry = function() {
// Will resolve the promise
$modalInstance.close();
};
$scope.cancel = function() {
// Will reject the promise
$modalInstance.dismiss();
}
});
А шаблон для модального окна может быть примерно таким:
<div class="modal-header">
<h3>Error!</h3>
</div>
<div class="modal-body">
<p>Something went wrong!</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="retry()">Retry</button>
<button class="btn btn-danger" ng-click="cancel()">Cancel</button>
</div>
который затем разрешит обещание при нажатии кнопки «Повторить попытку» или отклонит обещание при нажатии кнопки «Отмена».
Вы можете увидеть, как все это работает в этом Plunker.
Несколько дополнительных моментов:
Вы можете передать подробную информацию об исходной ошибке, используя параметр resolve
в $modal.open
, чтобы вы могли настроить отображаемое сообщение.
Возможно, вы не захотите отображать диалоговое окно для всех запросов. Если, например, при загрузке шаблона для модального окна произошла ошибка, вы получите бесконечный цикл. Вы можете проверить код состояния http, чтобы отображать диалоговое окно только при определенных сбоях, или другой способ управления этим - добавить пользовательские параметры к объекту config
, который вы передаете в $http
, который затем можно проверить в responseError
перехватчике, чтобы определить как устраняется сбой.
person
Michal Charemza
schedule
05.05.2014