Добавить несколько HTTP-перехватчиков в приложение Angular

86

Как добавить несколько независимых перехватчиков HTTP в приложение Angular 4?

Я попытался добавить их, расширив providersмассив более чем одним перехватчиком. Но фактически выполняется только последнее, Interceptor1игнорируется.

@NgModule({
  declarations: [ /* ... */ ],
  imports: [ /* ... */ HttpModule ],
  providers: [
    {
      provide: Http,
      useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =>
        new Interceptor1(xhrBackend, requestOptions),
      deps: [XHRBackend, RequestOptions],
    },
    {
      provide: Http,
      useFactory: (xhrBackend: XHRBackend, requestOptions: RequestOptions) =>
        new Interceptor2(xhrBackend, requestOptions),
      deps: [XHRBackend, RequestOptions]
    },
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Очевидно, я мог бы объединить их в один Interceptorкласс, и это должно сработать. Однако я бы хотел избежать этого, поскольку эти перехватчики имеют совершенно разные цели (один для обработки ошибок, один для отображения индикатора загрузки).

Итак, как я могу добавить несколько перехватчиков?

ул.
источник
2
Вы преобладаете Http. Используется только последнее изменение. Interceptor1 не игнорируется, его просто нет. Вы можете использовать HttpClient, в который включены перехватчики.
Estus Flask
@estus Что вы имеете в виду, говоря «Вы можете использовать HttpClient с включенными перехватчиками»?
str
angular.io/guide/http
Estus Flask
вы можете использовать разные перехватчики для запроса, ответа, используя это, с которым вы можете обрабатывать ошибки, индикатор загрузчика.
nivas
Есть ли обновления по этому вопросу?
Ренил Бабу

Ответы:

164

Httpне позволяет иметь более одной пользовательской реализации. Но, как упомянул @estus, команда Angular недавно добавила новую службу HttpClient (выпуск 4.3), которая поддерживает концепцию нескольких перехватчиков. Вам не нужно расширять, HttpClientкак вы это делаете со старым Http. HTTP_INTERCEPTORSВместо этого вы можете предоставить реализацию, которая может быть массивом с 'multi: true'опцией:

import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
...

@NgModule({
  ...
  imports: [
    ... ,
    HttpClientModule
  ],
  providers: [
    ... ,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: InterceptorOne,
      multi: true,
    },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: InterceptorTwo,
      multi: true,
    }
  ],
  ...
})

Перехватчики:

import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
...

@Injectable()
export class InterceptorOne implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('InterceptorOne is working');
    return next.handle(req);
  }
}

@Injectable()
export class InterceptorTwo implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('InterceptorTwo is working');
    return next.handle(req);
  }
}

Этот вызов сервера распечатает сообщения журнала обоих перехватчиков:

import {HttpClient} from '@angular/common/http';
...

@Component({ ... })
export class SomeComponent implements OnInit {

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.http.get('http://some_url').subscribe();
  }
}
hiper2d
источник
4
Есть ли способ сказать, что apiвызов может быть перехвачен только одним interceptor? или по каким-либо условиям?
k11k2 07
@ k11k2 и для всех, кто ищет, вот вопрос и ответ по этому поводу: stackoverflow.com/questions/45781379/… Признаюсь, я все еще немного смущен этим.
trollkotze
Почему должен быть @Injectable ()? У меня он работает без @Injectable ()
makkasi 03
1
@makkasi: необходимо добавить @ Injectable, если классу-перехватчику необходимо выполнить какое-либо собственное внедрение зависимостей. В данном примере это не обязательно
jintoppy 05
1
@ AmirReza-Farahlagha Interceptors вызываются в том порядке, в котором они предоставлены
hiper2d