使用 AngularJS Interceptors 向最终用户显示通知





5.00/5 (7投票s)
描述了一种使用 AngularJS 的 Interceptors 和 HTTP 方法向最终用户显示通知的通用方法。
引言
本文描述了一种通用的方法,使用 AngularJS 的拦截器和 HTTP 方法,根据用户的操作向最终用户显示通知。例如,如果用户正在发布记录,将显示“正在保存…
”的通知。如果用户正在删除记录,将显示“正在删除…
”的通知,依此类推。代码使用 AngularJS 和 Typescript。
背景
我有一个需求,需要在用户执行的每个操作上都显示通知,这样即使在与数据库通信时出现延迟等情况,用户也能知道正在发生一些事情。
例如,当用户尝试查看与联系人相关的所有关联记录时,将显示“正在加载…
”通知
一种方法是将通知服务注入到所有 AngularJS 服务中,然后根据操作显示通知,并在 promise 返回后隐藏通知。如果只有一页和几个操作,这很好;但是,如果需要在许多页面中重复此操作,这将违反 DRY 原则。
因此,更好的解决方案是使用 AngularJS 的拦截器 来拦截 Request
/ Response
并注入通知服务以显示通知。AngularJS 拦截器将使我们能够在执行请求之前和返回响应后注入自定义代码,并将其显示给最终用户。
请参阅下面的代码示例。我将在另一篇文章中展示通知服务的实际实现。
Using the Code
代码非常易于理解,但是重要的行是
- 使用 AngularJS 注册自定义 HTTP 拦截器
angular.module("CRM").config(['$httpProvider', ($httpProvider: any) => { $httpProvider.interceptors.push(HttpInterceptor.Factory); // Inject our custom interceptor }]);
- 在自定义拦截器中注入自定义通知服务
static $inject = ['$injector', '$q']; constructor($injector: ng.auto.IInjectorService, $q) { this.$q = $q; this.notificationService = $injector.get("CRM.Common.NotificationService"); this.$log = $injector.get('$log'); this.$injector = $injector; }
- 使用自定义通知服务并解析 HTTP 方法
public request = (config) => { this.notificationService.blockUi(this.getMessageBasedOnHttpMethod(config.method)); return config; };
完整的代码如下所示
module CRM.Config {
((): void => {
angular.module('CRM', [
'toaster',
'ngTasty',
'ui.bootstrap',
'darthwade.dwLoading']);
angular.module("CRM").config(['$httpProvider', ($httpProvider: any) => {
$httpProvider.defaults.headers.common['X-Requested-With'] =
'XMLHttpRequest'; // Make angular messages MVC Ajax compatible.
$httpProvider.interceptors.push(HttpInterceptor.Factory); // Inject our custom interceptor
}]);
})();
/**
* Custom Http Interceptor
*/
export class HttpInterceptor {
private $q;
public notificationService: CRM.Common.INotificationService; // Custom Notification Service
public $log: ng.ILogService;
public $injector: ng.auto.IInjectorService;
/**
* Show the error notification and unblock the UI
*/
public responseError = (rejection) => {
this.notificationService.unblockUi();
if (rejection.data.message) {
this.notificationService.showError(rejection.data.message);
}
return this.$q.reject(rejection);
};
/**
* Unblock the UI as there is no error in response
*/
public response = (response) => {
if (this.$q.when(response)) {
this.notificationService.unblockUi();
return this.$q.when(response);
}
return response || this.$q.when(response);
}
/**
* Block the UI and show notification based on the HTTP method
*/
public request = (config) => {
this.notificationService.blockUi(this.getMessageBasedOnHttpMethod(config.method));
return config;
};
private getMessageBasedOnHttpMethod(httpMethod : string): string {
var message = "";
switch (httpMethod.toLowerCase()) {
case "get":
message = "Loading...";
break;
case "post":
message = "Saving...";
break;
case "put":
message = "Updating...";
break;
case "delete":
message = "Deleting...";
break;
default:
message = "Please Wait...";
}
return message;
}
/**
* If there was any error while doing the request, unblock UI and show message
*/
public requestError = (rejection) => {
this.$log.log("requestError", rejection);
this.notificationService.unblockUi();
if (rejection.data.message) { // If MVC filter related errors
this.notificationService.showError(rejection.data.message);
}
return this.$q.reject(rejection);
};
public static Factory($injector, $q: ng.IQService) {
HttpInterceptor.Factory.$inject = ["$injector", "$q"];
return new HttpInterceptor($injector, $q);
}
static $inject = ['$injector', '$q'];
constructor($injector: ng.auto.IInjectorService, $q) {
this.$q = $q;
this.notificationService = $injector.get("CRM.Common.NotificationService");
this.$log = $injector.get('$log');
this.$injector = $injector;
}
}
}
历史
- 2015 年 12 月 27 日:初始版本