Você tem algumas opções, dependendo de suas necessidades. Se você quiser tratar os erros por solicitação, adicione um catch
à sua solicitação. Se você quiser adicionar uma solução global, use HttpInterceptor
.
Abra aqui o êmbolo de demonstração de trabalho para as soluções abaixo.
tl; dr
No caso mais simples, você só precisa adicionar um .catch()
ou um .subscribe()
, como:
import 'rxjs/add/operator/catch'; // don't forget this, or you'll get a runtime error
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});
// or
this.httpClient
.get("data-url")
.subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
Mas há mais detalhes sobre isso, veja abaixo.
Solução do método (local): registrar o erro e retornar a resposta de fallback
Se precisar lidar com erros em apenas um lugar, você pode usar catch
e retornar um valor padrão (ou resposta vazia) em vez de falhar completamente. Você também não precisa do .map
apenas para lançar, você pode usar uma função genérica. Fonte: Angular.io - Obtendo detalhes do erro .
Portanto, um .get()
método genérico seria como:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class DataService {
baseUrl = 'http://localhost';
constructor(private httpClient: HttpClient) { }
// notice the <T>, making the method generic
get<T>(url, params): Observable<T> {
return this.httpClient
.get<T>(this.baseUrl + url, {params})
.retry(3) // optionally add the retry
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value
// return Observable.of<any>({my: "default value..."});
// or simply an empty observable
return Observable.empty<T>();
});
}
}
Lidar com o erro permitirá que seu aplicativo continue, mesmo quando o serviço no URL estiver em más condições.
Essa solução por solicitação é boa principalmente quando você deseja retornar uma resposta padrão específica para cada método. Mas se você se preocupa apenas com a exibição de erros (ou tem uma resposta padrão global), a melhor solução é usar um interceptor, conforme descrito abaixo.
Execute o plunker de demonstração de trabalho aqui .
Uso avançado: interceptando todas as solicitações ou respostas
Mais uma vez, o guia Angular.io mostra:
Um dos principais recursos do @angular/common/http
é a interceptação, a capacidade de declarar interceptadores que ficam entre seu aplicativo e o back-end. Quando seu aplicativo faz uma solicitação, os interceptores a transformam antes de enviá-la ao servidor e podem transformar a resposta no caminho de volta antes que seu aplicativo a veja. Isso é útil para tudo, desde autenticação até registro.
Que, claro, pode ser usado para lidar com erros de uma forma muito simples ( plunker de demonstração aqui ):
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse,
HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value (which has to be a HttpResponse here)
// return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
// or simply an empty observable
return Observable.empty<HttpEvent<any>>();
});
}
}
Fornecendo seu interceptor: simplesmente declarar o HttpErrorInterceptor
acima não faz com que seu aplicativo o use. Você precisa conectá-lo ao seu módulo de app , fornecendo-o como um interceptor, da seguinte maneira:
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpErrorInterceptor } from './path/http-error.interceptor';
@NgModule({
...
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true,
}],
...
})
export class AppModule {}
Nota: Se você tem tanto um interceptor de erro e alguns manipulação de erro local, naturalmente, é provável que nenhum tratamento de erros local irá sempre ser acionado, desde que o erro será sempre tratado pelo interceptor antes que ele atinja o tratamento de erros local.
Execute o plunker de demonstração de trabalho aqui .
return this.httpClient.get<type>(...)
. e, em seguida, tercatch...
algum lugar fora do serviço onde ele realmente consome, porque é onde ele estará construindo um fluxo observável e poderá lidar com isso melhor.Promise<Object>
cliente de (o chamador dosDataService
métodos de) para lidar com o erro. Exemplo:this.dataService.post('url', {...}).then(...).catch((e) => console.log('handle error here instead', e));
. Escolha o que for mais claro para você e para os usuários do seu serviço.return Observable.of({my: "default value..."});
dá um erro "| ... 'não pode ser atribuído ao tipo' HttpEvent <qualquer> '."HttpEvent
, como aHttpResponse
. Assim, por exemplo, você poderia usar:return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
. Eu atualizei a resposta para deixar este ponto claro. Além disso, criei um plunker de demonstração funcional para mostrar tudo funcionando: plnkr.co/edit/ulFGp4VMzrbaDJeGqc6q?p=previewDeixe-me atualizar a resposta do acdcjunior sobre o uso do HttpInterceptor com os recursos RxJs mais recentes (v.6).
fonte
Com a chegada da
HTTPClient
API, não apenas aHttp
API foi substituída, mas uma nova foi adicionada, aHttpInterceptor
API.AFAIK um de seus objetivos é adicionar comportamento padrão a todas as solicitações de saída HTTP e respostas de entrada.
Portanto, supondo que você deseja adicionar um comportamento padrão de tratamento de erros , adicionar
.catch()
todos os métodos http.get / post / etc possíveis é ridiculamente difícil de manter.Isso pode ser feito da seguinte maneira, como exemplo, usando um
HttpInterceptor
:// app.module.ts
Algumas informações extras para OP: Chamar http.get / post / etc sem um tipo forte não é um uso ideal da API. Seu serviço deve ser assim:
Retornar
Promises
de seus métodos de serviço em vez deObservables
é outra má decisão.E um conselho extra: se você estiver usando o script TYPE , comece a usar a parte type dele. Você perde uma das maiores vantagens da linguagem: saber o tipo de valor com que está lidando.
Se você quiser, na minha opinião, um bom exemplo de serviço angular, dê uma olhada na essência a seguir .
fonte
this.http.get()
etc. e nãothis.get()
etc. emDataService
?Bastante simples (em comparação a como era feito com a API anterior).
Fonte (copie e cole) do guia oficial Angular
fonte
Para Angular 6+, .catch não funciona diretamente com Observable. Você tem que usar
Código abaixo:
Para obter mais detalhes, consulte o Guia Angular para Http
fonte
Exemplo de serviço de tratamento de erros de Angular 8 HttpClient
api.service.ts
fonte
Você provavelmente quer algo assim:
Depende muito também de como você usa seu serviço, mas este é o caso básico.
fonte
Seguindo a resposta de @acdcjunior, foi assim que eu o implementei
serviço:
chamador:
fonte
fonte
Se você não conseguir detectar erros com qualquer uma das soluções fornecidas aqui, pode ser que o servidor não esteja lidando com as solicitações CORS.
Nesse caso, o Javascript, muito menos o Angular, pode acessar as informações do erro.
Procure por avisos em seu console que incluam
CORB
ouCross-Origin Read Blocking
.Além disso, a sintaxe mudou para lidar com erros (conforme descrito em todas as outras respostas). Agora você usa operadores que permitem canalização, como:
fonte
Usando o Interceptor, você pode detectar erros. Abaixo está o código:
Você pode preferir este blog .. dado um exemplo simples para isso.
fonte