web-dev-qa-db-fra.com

Réessayez les requêtes HTTP dans angular 6

J'utilise un intercepteur pour afficher les messages d'erreur sur l'affichage en fonction de la réponse HTTP pour chaque demande.

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const customReq = request.clone({
        //headers: request.headers.set('app-language', 'en')
    });
    return next
        .handle(customReq).pipe(
            tap((ev: HttpEvent<any>) => {
                if (ev instanceof HttpResponse) {
                    // processing request
                }
            }),
            catchError(response => {
                if (response instanceof HttpErrorResponse) {
                    switch (response.status) {
                        case 0:
                            // server API connection error show
                            break;
                        case 403:
                            // error Token Invalid and Redirect to logout
                            break;
                        case 401:
                            // error Token Invalid and Redirect to logout
                            break;
                        case 502:
                            // Bad gateway error
                            break;
                        case 500:
                            // internal server error
                            break;
                    }
                }
                // return next.handle(request);
                return observableThrowError(response);
            })
        );
}

Dans mon projet, le serveur Web pourrait être indisponible pendant une seconde dans certains cas et répondre à un code d'erreur 500. Je ne veux pas que mon application Web affiche un message d'erreur immédiatement après avoir reçu une erreur et je veux qu'elle réessaye la demande plusieurs fois avec un délai comme une seconde.

J'ai déjà essayé de réessayer rxjs:

...
.handle(customReq).pipe(retry(5),
...

ce n'est pas utile car il n'a pas de retard. basé sur cette réponse Comment créer un RXjs RetryWhen avec délai et limite sur les essais

J'ai essayé de réessayer

.handle(customReq).pipe(
    tap((ev: HttpEvent<any>) => {
        if (ev instanceof HttpResponse) {
            console.log('###processing response', ev, this.location);
        }
    }),
    retryWhen(error => {
        return error
            .flatMap((error: any) => {
                if (error.status  == 400) {
                    return Observable.of(error.status).delay(1000);
                }
                if (error.status  == 0) {
                    return observableThrowError(error).delay(1000);
                }
                return observableThrowError(error);
            })
            .take(5)
            .concat(observableThrowError(error));
    }),

mais cela ne fonctionne pas comme prévu et ne rentre pas dans les conditions if.

6
Amir Khademi

Il y a plusieurs erreurs dans votre code:

  1. Vous observez la variable error - c'est d'abord un flux d'erreur, puis un objet erreur.
  2. L'utilisation de observableThrowError avec delay n'a aucun effet. L'erreur contournera tous les opérateurs, sauf ceux qui traitent d'erreur.
  3. Vous mélangez les opérateurs de style "pipe(operator())" et les opérateurs de style prototype .operator().

J'ai suggéré quelques changements:

.handle(customReq).pipe(
    tap((ev: HttpEvent<any>) => {
        if (ev instanceof HttpResponse) {
            console.log('###processing response', ev, this.location);
        }
    }),
    retryWhen(errors => errors
        .pipe(
            concatMap((error, count) => {
                if (count < 5 && (error.status == 400 || error.status == 0)) {
                    return Observable.of(error.status);
                }

                return observableThrowError(error);
            }),
            delay(1000)
        )
    ),

La principale modification consiste à suivre le nombre d'erreurs via le deuxième argument de concatMap au lieu d'utiliser take opeator, ce qui est principalement utile pour se désabonner de l'observable et je pense que vous souhaitez plutôt lancer une erreur.

10
m1ch4ls

Le blog suivant vous explique comment réessayer les requêtes HTTP qui ont échoué. Il vous donne également différentes stratégies sur la façon de gérer les tentatives.

https://blog.angularindepth.com/retry-failed-http-requests-in-angular-f5959d486294?source=activity---post_recommended_rollup

1
Trafalgar