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?

25
demandé sur Jota.Toledo 2017-08-29 15:15:51

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.

40
répondu estus 2018-05-03 15:59:24

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 {
}
10
répondu Rahul Singh 2017-08-30 06:25:24

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.

8
répondu Jota.Toledo 2017-08-29 14:01:03