Como ter uma nova tentativa de requisição HTTP no Angular (vários códigos como exemplo)


Como lidar com uma falha na requisição HTTP?

Aqui estão algumas linha de códigos com Angular que você pode usar para administrar as falhas HTTP.

Algumas aplicações com Angular podem ser tão desengonçadas como um elefante jogando bola.

Quando eles erram, caem de verdade.

E outras são tão habilidosas como um Ronaldinho Gáucho.

Quer saber como você pode fazer sua aplicação com Angular ser mais ágil e resistente através da resolução das falhas HTTP? Continue lendo.

Vamos começar com o interceptor HTTP

Abra um terminal no seu projeto Angular e prepare o Angular CLI, desse jeito:

ng generate interceptor monitor

Então vamos importar isso para nosso arquivo de módulo, adicionando aos providers.

providers: [
    { 
      provide: HTTP_INTERCEPTORS, 
      useClass: MonitorInterceptor, 
      multi: true
    }
]

Acione o interceptor para tentar novamente a requisição que falhou.

Depois vamos abrir um novo arquivo de monitor.interceptor.ts. Deve ser algo parecido com isto:

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

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request);
  }
}

Como talvez você já saiba, esse interceptor pode ser utilizado para modificar qualquer requisição HTTP recebida ou enviada.

Como conseguir as vantagens de um interceptor Angular? A resposta é bem simples.

Para adicionar a capacidade de tentativas nós vamos usar a função de laços de repetição que aciona uma tentativa quando a observabilidade falha.

É assim que se faz:

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

export const retryCount = 3;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      retry(retryCount)
    )
  }
}

Pronto, agora se alguma requisição HTTP falhar ele vai repetir a requisição mais 3 vezes.

Como repetir a requisição dependendo do código de status de respostas?

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable, of, throwError } from 'rxjs';
import { concatMap, delay, retryWhen } from 'rxjs/operators';

export const retryCount = 3;
export const retryWaitMilliSeconds = 1000;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      retryWhen(error => 
        error.pipe(
          concatMap((error, count) => {
            if (count <= retryCount && error.status == 503) {
              return of(error);
            }
            return throwError(error);
          }),
          delay(retryWaitMilliSeconds)
        )
      )
    )
  }
}

Como reenviar requisição depois de uma autenticação ter sido efetuada através de uma atualização ou refresh?

Como lidar com uma situação onde o servidor responde com um 401? Você precisa fazer alguma espécie de login ou dar refresh na página?

Esse é o código:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';

export const retryCount = 3;

@Injectable()
export class MonitorInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(catchError(error => {
        if (error.status === 401) {
          return this.reAuthenticate().pipe(
            switchMap(() => next.handle(request))
          )
        }
        return throwError(error);
      })
    )
  }

  reAuthenticate(): Observable<any> {
    // Do your auth call here
  }
}

Conclusão

Nesse guia demos uma olhada em diferentes maneiras de lidar com uma falha na requisição HTTP.

Às vezes uma falha parece ser apenas um pequeno detalhe que não vale a pena esquentar a cabeça, mas quando consertadas do jeito correto, seus usuários vão com certeza agradecer a você.

Dúvidas ou comentários? Por favor, não hesite em entrar em contato comigo.

Consultor e Freelancer Angular