我可以理解如何使用this question
中的重试逻辑来生成$ http请求拦截器但我无法弄清楚如何使用重试按钮制作模态弹出窗口(angular-ui - bootstrap),每次出现错误时都会加速,甚至反复出现。有人可以给我一些建议吗?
答案 0 :(得分:4)
这有很多组件,您需要了解链接承诺,以了解它们如何组合在一起。首先是拦截器
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
承诺解析/拒绝的promise。如果该承诺得到解决,那么它将重试原始的$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>
然后将解决承诺,如果&#34;重试&#34;单击,或拒绝承诺,如果&#34;取消&#34;点击。
你可以see all this working in this Plunker。
加分:
您可以使用resolve
选项将原始失败的详细信息传递给$modal.open
,以便您自定义显示的消息。
您可能不希望显示所有请求的对话框。例如,如果为模态获取模板时出错,则最终会出现无限循环。您可以测试http状态代码仅显示某些失败的对话框,或者另一种控制方法是向您传递给config
的{{1}}对象添加自定义选项,然后您可以测试在$http
拦截器中,确定如何处理失败。
答案 1 :(得分:0)
查看此Angular模块http://ngmodules.org/modules/http-auth-interceptor它用于拦截未授权的请求并重试它们。您可以根据需要轻松调整此模块。用您的逻辑替换if (rejection.status === 401 && !rejection.config.ignoreAuthModule)
。在'event:auth-loginConfirmed'
与$rootScope.$on('event:auth-loginConfirmed', ...)
绑定app.run()
事件以打开您的模态。在您的模态注入authService
工厂并调用authService.loginConfirmed()
时,这将使用您的错误逻辑重试请求