web-dev-qa-db-fra.com

Délai d'attente de demande par défaut et spécifique

En général, il est souhaitable d’avoir un délai d’expiration par défaut (par exemple 30 secondes) qui sera appliqué à toutes les demandes et peut être remplacé pour des demandes particulières plus longues (par exemple 600 secondes).

À ma connaissance, il n’existe aucun moyen de spécifier le délai d’expiration par défaut dans le service Http.

Quelle est la façon d'aborder cela dans HttpClient service? Comment définir un délai d'attente par défaut pour toutes les demandes sortantes, pouvant être remplacé pour des demandes spécifiques?

36
Estus Flask

Il semble que sans étendre les classes HttpClientModule, les seuls moyens prévus pour que les intercepteurs communiquent avec les requêtes respectives sont les objets params et headers.

La valeur du délai d’expiration étant scalaire, elle peut être fournie en toute sécurité sous forme d’en-tête personnalisé à l’intercepteur, qui permet de déterminer s’il s’agit du délai d’expiration par défaut ou spécifique à appliquer via l’opérateur RxJS timeout:

import { Inject, Injectable, InjectionToken } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';

export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');

@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
  constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const timeoutValue = Number(req.headers.get('timeout')) || this.defaultTimeout;

    return next.handle(req).pipe(timeout(timeoutValue));
  }
}

Cela peut être configuré dans votre module d'application comme:

...
providers: [
  [{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
  [{ provide: DEFAULT_TIMEOUT, useValue: 30000 }]
],  
...

La demande est ensuite effectuée avec l'en-tête personnalisé timeout

http.get(..., { headers: new HttpHeaders({ timeout: `${20000}` }) });

Étant donné que les en-têtes sont supposés être des chaînes, la valeur de délai d'attente doit d'abord être convertie en chaîne.

Voici ne démo .

Les crédits vont à @RahulSingh et @ Jota.Toledo pour avoir suggéré l’idée d’utiliser des intercepteurs avec timeout.

78
Estus Flask

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);
        }
    });
  }
}

Ajouter un timeout à la next.handle(req) qui est transmise.

L'enregistrement dans AppModule comme

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        HttpClientModule
    ],
    providers: [
        [ { provide: HTTP_INTERCEPTORS, useClass: 
              AngularInterceptor, multi: true } ]
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}
10
Rahul Singh

Vous pouvez créer un global interceptor avec la valeur du délai d'attente 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 providers de votre module racine.

La partie délicate serait de remplacer le temps par défaut (augmentation/diminution) pour des demandes spécifiques. Pour le moment, je ne sais pas comment résoudre ce problème.

9
Jota.Toledo