【问题标题】:What is httpinterceptor equivalent in angular2?angular2中的httpinterceptor等价物是什么?
【发布时间】:2016-05-31 14:55:33
【问题描述】:

在angularjs中,我们有http拦截器

$httpProvider.interceptors.push('myHttpInterceptor');

我们可以使用它来挂钩所有 http 调用,显示或隐藏加载栏,进行日志记录等。

angular2中的等价物是什么?

【问题讨论】:

标签: http angular


【解决方案1】:

正如@Günter 指出的那样,没有办法注册拦截器。您需要扩展 Http 类并将您的拦截处理放在 HTTP 调用周围

首先你可以创建一个扩展Http的类:

@Injectable()
export class CustomHttp extends Http {
  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    console.log('request...');
    return super.request(url, options).catch(res => {
      // do something
    });        
  }

  get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    console.log('get...');
    return super.get(url, options).catch(res => {
      // do something
    });
  }
}

并按如下所述进行注册:

bootstrap(AppComponent, [HTTP_PROVIDERS,
    new Provider(Http, {
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
      deps: [XHRBackend, RequestOptions]
  })
]);

requestrequestError 可以在调用目标方法之前添加。

对于response 之一,您需要在现有处理链中插入一些异步处理。这取决于您的需要,但您可以使用 Observable 的运算符(如 flatMap)。

最后对于responseError 之一,您需要在目标调用上调用catch 运算符。这样,当响应中出现错误时,您会收到通知。

此链接可以帮助您:

【讨论】:

  • 一个很好的解释,我找到了另一个很好的解释:illucit.com/blog/2016/03/…
  • bootstrapping 在 angular2 中似乎不再以这种方式工作了。
  • 此解决方案不再起作用。自举已经改变。你能相应地更新答案吗?
【解决方案2】:

更新

Angular 4.3.0 中引入的新HttpClient 模块支持拦截器https://github.com/angular/angular/compare/4.3.0-rc.0...4.3.0

feat(common): 新的 HttpClient API HttpClient 是 现有的 Angular HTTP API,它与它一起存在于一个单独的 包,@angular/common/http。这种结构确保现有 代码库可以慢慢迁移到新的 API。

新 API 显着改进了人体工程学和功能 旧版 API。部分新功能列表包括:

  • 类型化的同步响应正文访问,包括对 JSON 正文类型的支持
  • JSON 是假定的默认值,不再需要显式解析
  • 拦截器允许将中间件逻辑插入到管道中
  • 不可变的请求/响应对象
  • 请求上传和响应下载的进度事件
  • 请求后验证和基于刷新的测试框架

原创

Angular2 没有(还)拦截器。您可以改为扩展 HttpXHRBackendBaseRequestOptions 或任何其他涉及的类(至少在 TypeScript 和 Dart 中(不了解普通 JS)。

另见

【讨论】:

    【解决方案3】:

    此存储库中有一个类似 Http @angular/core 的服务的实现:https://github.com/voliva/angular2-interceptors

    您只需在引导程序中声明该服务的提供者,添加您需要的任何拦截器,它就可用于所有组件。

    import { provideInterceptorService } from 'ng2-interceptors';
    
    @NgModule({
      declarations: [
        ...
      ],
      imports: [
        ...,
        HttpModule
      ],
      providers: [
        MyHttpInterceptor,
        provideInterceptorService([
          MyHttpInterceptor,
          /* Add other interceptors here, like "new ServerURLInterceptor()" or
             just "ServerURLInterceptor" if it has a provider */
        ])
      ],
      bootstrap: [AppComponent]
    })
    

    【讨论】:

      【解决方案4】:

      自 Angular 4.3 以来已被删除(HttpInterCeptors 回到 4.3)

      您可以创建自己的自定义 HTTP 类并使用 rxjs 主题服务来重用您的自定义 Http 类并在自定义类中实现您的行为。

      使用包含一些 rxjs 主题的“HttpSubjectService”实现您的自定义 Http 类。

      import { Injectable } from '@angular/core';
      import { Http, ConnectionBackend, Request, RequestOptions, RequestOptionsArgs, Response } from '@angular/http';
      import { Observable } from 'rxjs/Observable';
      
      
      import { HttpSubjectService } from './httpSubject.service';
      
      
      @Injectable()
      export class CustomHttp extends Http {
         constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private httpSubjectService: HttpSubjectService) {
             super(backend, defaultOptions);
      
             //Prevent Ajax Request Caching for Internet Explorer
             defaultOptions.headers.append("Cache-control", "no-cache");
             defaultOptions.headers.append("Cache-control", "no-store");
             defaultOptions.headers.append("Pragma", "no-cache");
             defaultOptions.headers.append("Expires", "0");
         }
      
         request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
             //request Start;
             this.httpSubjectService.addSpinner();
             return super.request(url, options).map(res => {
                 //Successful Response;
                 this.httpSubjectService.addNotification(res.json());
                 return res;
             })
                 .catch((err) => {
                     //Error Response.
                     this.httpSubjectService.removeSpinner();
                     this.httpSubjectService.removeOverlay();
      
                     if (err.status === 400 || err.status === 422) {
                         this.httpSubjectService.addHttp403(err);
                         return Observable.throw(err);
                     } else if (err.status === 500) {
                         this.httpSubjectService.addHttp500(err);
                         return Observable.throw(err);
                     } else {
                         return Observable.empty();
                     }
                 })
                 .finally(() => {
                     //After the request;
                     this.httpSubjectService.removeSpinner();
                 });
         }
      }
      

      用于注册您的 CustomHttp 类的自定义模块 - 在这里您使用您自己的 CustomHttp 实现覆盖来自 Angular 的默认 Http 实现。

      import { NgModule, ValueProvider } from '@angular/core';
      import { HttpModule, Http, XHRBackend, RequestOptions } from '@angular/http';
      
      //Custom Http
      import { HttpSubjectService } from './httpSubject.service';
      import { CustomHttp } from './customHttp';
      
      @NgModule({
          imports: [ ],
          providers: [
              HttpSubjectService,
              {
                 provide: Http, useFactory: (backend: XHRBackend, defaultOptions: RequestOptions, httpSubjectService: HttpSubjectService) => {
                      return new CustomHttp(backend, defaultOptions, httpSubjectService);
                  },
                  deps: [XHRBackend, RequestOptions, HttpSubjectService]
              }
          ]
      })
      export class CustomHttpCoreModule {
      
          constructor() { }
      }
      

      现在我们需要 HttpSubjectService 实现,当我们使用“next”语句调用它们时,我们可以订阅我们的 rxjs 主题。

      import { Injectable } from '@angular/core';
      import { Subject } from 'rxjs/Subject';
      
      @Injectable()
      export class HttpSubjectService {
          //https://github.com/ReactiveX/rxjs/blob/master/doc/subject.md
          //In our app.component.ts class we will subscribe to this Subjects
          public notificationSubject = new Subject();
          public http403Subject = new Subject();
          public http500Subject = new Subject();
          public overlaySubject = new Subject();
          public spinnerSubject = new Subject();
      
          constructor() { }
      
          //some Example methods we call in our CustomHttp Class
          public addNotification(resultJson: any): void {
              this.notificationSubject.next(resultJson);
          }
      
          public addHttp403(result: any): void {
              this.http403Subject.next(result);
          }
      
          public addHttp500(result: any): void {
              this.http500Subject.next(result);
          }
      
          public removeOverlay(): void {
              this.overlaySubject.next(0);
          }
      
          public addSpinner(): void {
              this.spinnerSubject.next(1);
          }
      
          public removeSpinner(): void {
              this.spinnerSubject.next(-1);
          }
      }
      

      要调用您的自定义实现,我们需要订阅主题,例如“app.component.ts”。

      import { Component } from '@angular/core';
      import { HttpSubjectService } from "../HttpInterception/httpSubject.service";
      import { Homeservice } from "../HttpServices/home.service";
      
      @Component({
          selector: 'app',
          templateUrl: './app.component.html',
      })
      export class AppComponent {
          private locals: AppLocalsModel = new AppLocalsModel();
      
          constructor(private httpSubjectService : HttpSubjectService, private homeService : Homeservice) {}
      
          ngOnInit(): void {
              this.notifications();
              this.httpRedirects();
              this.spinner();
              this.overlay();
          }
      
          public loadServiceData(): void {
              this.homeService.getCurrentUsername()
                  .subscribe(result => {
                      this.locals.username = result;
                  });
          }
      
          private overlay(): void {
              this.httpSubjectService.overlaySubject.subscribe({
                  next: () => {
                    console.log("Call Overlay Service");
                  }
              });
          }
      
          private spinner(): void {
              this.httpSubjectService.spinnerSubject.subscribe({
                  next: (value: number) => {
                    console.log("Call Spinner Service");
                  }
              });
          }
      
          private notifications(): void {
              this.httpSubjectService.notificationSubject.subscribe({
                  next: (json: any) => {
                      console.log("Call Notification Service");
                  }
              });
          }
      
          private httpRedirects(): void {
              this.httpSubjectService.http500Subject.subscribe({
                  next: (error: any) => {
                      console.log("Navigate to Error Page");
                  }
              });
      
              this.httpSubjectService.http403Subject.subscribe({
                  next: (error: any) => {
                      console.log("Navigate to Not Authorized Page");
                  }
              });
          }
      }
      
      
      class AppLocalsModel {
          public username : string = "noch nicht abgefragt";
      }
      

      从 ANGULAR 4.3 开始,您可以使用 InterCeptors

      在 Angular 4.3 中,您拥有原生拦截器,您可以在其中实现自己的东西,例如针对服务器错误 500 的重定向

      import { Injectable } from '@angular/core';
      import { Router } from '@angular/router';
      import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http';
      import { Observable } from 'rxjs/Observable';
      import 'rxjs/add/operator/do';
      import 'rxjs/add/operator/catch';
      import 'rxjs/add/observable/throw';
      
      @Injectable()
      export class SxpHttp500Interceptor implements HttpInterceptor {
      
        constructor(public router: Router) { }
      
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            return next.handle(req).do(evt => { }).catch(err => {
                if (err["status"]) {
                    if (err.status === 500) {
                        this.router.navigate(['/serverError', { fehler: JSON.stringify(err) }]);
                    }
                }
                return Observable.throw(err);
            });
        }
      }
      

      你需要在你的核心模块中注册这个 providers 数组

      import { HTTP_INTERCEPTORS } from '@angular/common/http';
      import { Router } from '@angular/router';
      import { SxpHttp500Interceptor } from "./sxpHttp500.interceptor";
       ....
      
      providers: [
          {
              provide: HTTP_INTERCEPTORS, useFactory: (router: Router) => { return new SxpHttp500Interceptor(router) },
              multi: true,
              deps: [Router]
          }
      ]
      

      【讨论】:

      【解决方案5】:

      在 Angular 4.3.1 版本中,现在有一个名为 HttpInterceptor 的接口。

      这是文档的链接: https://angular.io/api/common/http/HttpInterceptor

      这是一个实现示例。


      这将是拦截器类的实现。

      基本上写成任何其他服务:

      @Injectable()
      export class ExceptionsInterceptor implements HttpInterceptor {
          constructor(
              private logger: Logger,
              private exceptionsService: ExceptionsService,
              private notificationsService: NotificationsService
          ) { }
          intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      
              return next.handle(request)
                  .do((event) => {
                      // Do nothing here, manage only errors
                  }, (err: HttpErrorResponse) => {
                      if (!this.exceptionsService.excludeCodes.includes(err.status)) {
                          if (!(err.status === 400 && err.error['_validations'])) {
                              this.logger.error(err);
                              if (!this.notificationsService.hasNotificationData(err.status)) {
                                  this.notificationsService.addNotification({ text: err.message, type: MessageColorType.error, data: err.status, uid: UniqueIdUtility.generateId() });
                              }
                          }
                      }
                  });
          }
      }
      

      然后,由于您将其视为普通服务,因此您必须在应用模块的提供程序中添加此行:

      { provide: HTTP_INTERCEPTORS, useClass: ExceptionsInterceptor, multi: true }
      

      希望对你有帮助。

      【讨论】:

      • 还有,实现在哪里?
      • 有用的导入:import { HTTP_INTERCEPTORS } from "@angular/common/http";, import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
      • NotificationsService 无法在全球范围内工作。有什么建议吗? github.com/flauc/angular2-notifications
      【解决方案6】:

      Angular 4.3 现在支持开箱即用的 Http 拦截器。 查看如何使用它们: https://ryanchenkie.com/angular-authentication-using-the-http-client-and-http-interceptors

      【讨论】:

        【解决方案7】:

        我已经发布了带有以下节点模块的拦截器。我们为内部目的创建了这个模块,最后我们在 npm 包管理器中发布 npm install angular2-resource-and-ajax-interceptor https://www.npmjs.com/package/angular2-resource-and-ajax-interceptor

        【讨论】:

          【解决方案8】:

          正如@squadwuschel 所指出的,正在努力将此功能引入@angular/http。这将以新的 HttpClient API 的形式出现。

          有关更多详细信息和当前状态,请参阅https://github.com/angular/angular/pull/17143

          【讨论】:

            【解决方案9】:

            Angular2 不支持像 angular1 这样的 httpinterceptor

            这是在 angular2 中使用 httpinterceptor 的绝佳示例。

            https://github.com/NgSculptor/ng2HttpInterceptor

            【讨论】:

              【解决方案10】:

              试试Covalent from Teradata,他们为 Angular 和 Angular Material 提供了很多扩展。

              检查HTTP部分,它提供了Angular和RESTService中缺少的http拦截器(类似于restangular)。

              我在我的示例中通过 Covalent HTTP 实现了JWT 令牌认证,请在此处查看。

              https://github.com/hantsy/angular2-material-sample/blob/master/src/app/core/auth-http-interceptor.ts

              阅读我的开发笔记,Handle token based Authentication via IHttpInterceptor

              【讨论】:

              猜你喜欢
              • 2016-08-13
              • 2014-05-08
              • 2017-03-28
              • 1970-01-01
              • 2014-06-12
              • 1970-01-01
              • 2022-11-28
              • 2021-06-19
              • 2012-07-20
              相关资源
              最近更新 更多