Angular HttpClient default et délai d'attente de requête spécifique
Habituellement, il est souhaitable d'avoir un délai d'attente par défaut (par exemple 30s) qui sera appliqué à toutes les requêtes et peut être remplacé pour des requêtes plus longues (par exemple 600s).
Il n'y a pas de bon moyen de spécifier le délai d'attente par défaut dans Http
, à ma connaissance.
Quelle est la façon d'aborder cela dans HttpClient
?
Comment définir un délai d'attente par défaut pour toutes les requêtes sortantes, qui peuvent être remplacées pour des requêtes spécifiques?
3 réponses
Il semble que sans étendre les classes HttpClientModule
, les seuls moyens attendus pour les intercepteurs de communiquer avec les requêtes respectives sont les objets params
et headers
.
Étant donné que la valeur de délai d'attente est scalaire, elle peut être fournie en toute sécurité en tant qu'en-tête personnalisé à l'intercepteur, où il peut être décidé si c'est un délai d'attente par défaut ou spécifique qui doit être appliqué via RxJS timeout
Opérateur:
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/timeout';
const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
const defaultTimeout = 10000;
@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const timeout = Number(req.headers.get('timeout')) || this.defaultTimeout;
return next.handle(req).timeout(timeout);
}
}
...
providers: [
[{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
[{ provide: DEFAULT_TIMEOUT, useValue: defaultTimeout }]
],
...
La requête est ensuite effectuée avec l'en-tête timeout
personnalisé
http.get(..., { headers: new HttpHeaders({ timeout: `${20000}` }) });
Puisque les en-têtes sont supposés être chaînes, la valeur de délai d'attente doit d'abord être convertie en chaîne.
Ici une démo.
Les crédits vont à @ RahulSingh et @Jota.Toledo pour avoir suggéré l'idée d'utiliser des intercepteurs avec timeout
.
En utilisant le nouveau HttpClient, vous pouvez essayer quelque chose comme ceci
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(5000).do(event => {}, err => { // timeout of 5000 ms
if(err instanceof HttpErrorResponse){
console.log("Error Caught By Interceptor");
//Observable.throw(err);
}
});
}
}
Ajout d'un délai d'attente au next.handle(req)
qui est transmis.
L'enregistrer dans AppModule comme
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
[ { provide: HTTP_INTERCEPTORS, useClass:
AngularInterceptor, multi: true } ]
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Vous pouvez créer un intercepteur global avec la valeur de timeout de base comme suit:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(30000, Observable.throw("Request timed out"));
// 30000 (30s) would be the global default for example
}
}
Ensuite, vous devez enregistrer cet injectable dans le tableau des fournisseurs de votre module racine.
La partie délicate serait de remplacer l'heure par défaut (augmentation/diminution) pour des demandes spécifiques. Pour le moment je ne sais pas comment résoudre ce problème.