Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

Angular não esta capturando os erros em uma requisição HTTP

Pessoal tenho o seguinte código que faz uma requisição para uma API em ASP.NET Core.

getClientePessoa(cpf: string) {
        if (cpf.length == 11) {

            this.modalCadastrarPrecService
                .getClientePessoa(cpf)
                .subscribe((cliente: TblCliente) => {
                    console.log(cliente);
                },
                    (error) => {
                        console.log(error);
                    }
                )

        } else {
            console.log('teste');
        }
    }

Quando ele tem sucesso ele me retorna o objeto perfeitamente, porem quando emite um erro o angular não consegue capturar este erro e da a seguinte mensagem no console .

Erro no console quando eu retorno um BadRequest(exception) no backend.

core.js:14597 ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    at subscribeTo (subscribeTo.js:41)
    at subscribeToResult (subscribeToResult.js:11)
    at CatchSubscriber.push../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:43)
    at XMLHttpRequest.onLoad (http.js:1547)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:16147)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
    at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
    at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:498)
    at invokeTask (zone.js:1744)

Não sei o que fazer para o angular capturar o erro corretamente e emitir uma mensagem, alguém poderia me ajudar?

8 respostas

Fala aí Tamires, tudo bem? Como está o ModalCadastrarPrecService? Mais especificamente a função/método getClientePessoa.

Precisaria dar uma olhada no código completo para tentar entender melhor o problema, ele pode ser causado por diversas razões.

Consegue mandar o código?

Provavelmente deve estar faltando realizar algum tratamento na sua requisição HTTP quando ocorre erro.

Fico no aguardo.

Aqui esta

 getClientePessoa(cpf: string){
        return this.http.get(URL_API + `/Cliente/Pessoa/${cpf}`);
    }

Estranho Tamires, está ok o service e a maneira como está utilizando ele.

Você configurou algum Interceptor?

Outro detalhe: Consegue me mandar o projeto para simular o problema aqui, ficaria mais fácil visualizá-lo e entendê-lo para lhe ajudar.

Fico no aguardo, bons estudos.

Eu teria que te mandar o backend também? Porque o banco de dados fica em um servidor que não tem acesso a não ser pelo endereços autorizados pelo pessoal onde trabalho.

Para voce, apenas o front em angular serve?

Eu tenho sim um interceptor configurado, vou encaminhar aqui embaixo

REQUEST INTERCEPTOR

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpClient } from '@angular/common/http';

import { Observable } from 'rxjs';
import { catchError, flatMap, retry } from 'rxjs/operators';

import { TokenService } from '../token/token.service';
import { ResponseModel } from '../../models/response';
import { UserService } from '../user/user.service';
import { environment } from 'src/environments/environment';

const URL_API = environment.ApiUrl;

@Injectable()
export class RequestInterceptor implements HttpInterceptor {

    isRefreshingToken: boolean = false;

    //classe responsável por interceptar todas as requisições para o servidor e setar um token caso exista
    constructor(
        private tokenService: TokenService,
        private router: Router,
        private userService: UserService,
        private http: HttpClient
    ) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        if (this.tokenService.hasToken()) {
            const token = this.tokenService.getToken();
            //clonando a requisição e setando o header com o token

            if (token) {
                req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
            }

            if (!req.headers.has('Content-Type')) {
                req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
            }

            req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
        }

        //verificando erros do retorno para fazer ou não uma nova requisição
        return next.handle(req).pipe(catchError((error) => {

            if (error.status == 401 && error.statusText == "OK") {

                var userId = this.userService.getUser().unique_name;
                var refreshToken = this.tokenService.getRefreshToken()

                //refazendo a requisição para o refresh token
                return this.http.post(URL_API + '/login',
                    { userId, refreshToken, grantType: 'refresh_token', },//body
                    { observe: 'response' })

                    //mesclando as requisições e emitindo apenas uma no final
                    .pipe(flatMap(res => {
                        let responseModel = (<ResponseModel>res.body.valueOf());

                        //caso o token retornado seja difirente undefined, significa que o token secundario ainda é valido
                        if (responseModel.accessToken != undefined) {

                            this.userService.setToken(responseModel.accessToken);
                            this.userService.setRefreshToken(responseModel.refreshToken);

                            //criando e emitindo uma nova requisição requisição com os dados do token atualizado
                            const cloneReq = req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + responseModel.accessToken) });
                            return next.handle(cloneReq);

                        } else {
                            this.router.navigate(['/not-authorized']);
                            this.tokenService.deleteToken();
                        }
                    }));
            }
        }));
    }
}
solução!

Realmente o problema está no interceptor, repare que você está verificando se o requisição deu algum erro através do seu interceptor, porém, caso ele não entre no if você não está retornando nada.

Isso é o mótivo da mensagem de erro:

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Era esperado um retorno que seja Observable, Promise, Array ou Ireable, mas, você retornou undefined.

Foi retornado undefined porque na verdade você não retornou nada.

Para resolver o problema e passar a validação de erro para quem chama seus services, você pode lançar um erro dentro do seu catchError:

throw error;

Isso pode ser feito em baixo do if, dessa maneira, se ele entrar no if vai retornar o retorno de http.post senão vai retornar o erro com throw error.

Espero ter ajudado.

Vou testar, se der certo eu aviso voce, obrigado por toda a ajuda.

Deu tudo certo, falta de atenção minha, muito obrigado pela ajuda =D...

Magina, sempre que precisar não deixe de criar suas dúvidas.

Abraços e bons estudos.