Ainda não tem acesso? Estude com a gente! Matricule-se
Ainda não tem acesso? Estude com a gente! Matricule-se

Solucionado (ver solução)

handleError não capturando os erros da aplicação

Olá, estou com este problema onde os erros da minha aplicação não estão sendo capturados pelo meu handleError não sei se esqueci de algo na implementação. Alguém poderia ajudar?

Segue código:

global-error-handler.ts

import { ErrorHandler, Injectable, Injector } from "@angular/core";
import * as StackTrace from 'stacktrace-js';
import { LocationStrategy, PathLocationStrategy } from "@angular/common";
import { Router } from "@angular/router";
import { environment } from "../../../environments/environment"

import { UserService } from "../../core/user/user.service";
import { ServerLogService } from "./server-log.service";

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {

    constructor(private injector: Injector) {}

    handleError(error: any): void {
        console.log("Passou pelo handler");
        const location = this.injector.get(LocationStrategy);
        const userService = this.injector.get(UserService);
        const serverLogService = this.injector.get(ServerLogService);
        const router = this.injector.get(Router);

        const url = location instanceof PathLocationStrategy 
            ? location.path()
            : '';

        const message = error.message ? error.message : error.toString();

        if(environment.production) router.navigate(['/error']);

        StackTrace
            .fromError(error)
            .then(stackFrames => {
                const stackAsString = stackFrames
                    .map(sf => sf.toString())
                    .join('\n')
                console.log(message);
                console.log(stackAsString);
                console.log("oque será enviado para o servidor:");
                serverLogService
                    .log({ 
                        message, 
                        url, 
                        userName: userService.getUserName(), 
                        stack: stackAsString}
                    ).subscribe(
                        () => console.log("Error logged on server"),
                        err => {
                            console.log(err);
                            console.log("Fail to send error log to server");
                        }
                    );
            });
    }
}

errors.module.ts

import { NgModule, ErrorHandler } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';

import { NotFoundComponent } from './not-found/not-found.component';
import { GlobalErrorHandler } from './global-error-handler/global-error-handler';
import { GlobalErrorComponent } from './global-error/global-error.component';

@NgModule({
  imports: [
    CommonModule,
    RouterModule
  ],
  declarations: [
    NotFoundComponent,
    GlobalErrorComponent
  ],
  providers: [
    {
      provide: ErrorHandler,
      useClass: GlobalErrorHandler
    }
  ]
})
export class ErrorsModule { }

app.module.ts

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing.module';
import { HttpClientModule } from '@angular/common/http';

import { ErrorsModule } from './errors/errors.module';
import { CoreModule } from './core/core.module';
import { ShowIfLoggedModule } from './shared/directives/show-if-logged/show-if-logged.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MAT_MOMENT_DATE_FORMATS, MomentDateAdapter} from '@angular/material-moment-adapter';
import { MAT_DATE_LOCALE, DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ErrorsModule,
    CoreModule,
    HttpClientModule,
    ShowIfLoggedModule,
    AppRoutingModule,
    BrowserAnimationsModule
  ],
  providers: [
    {provide: MAT_DATE_LOCALE, useValue: 'pt-BR'},
    {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
    {provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS}
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
10 respostas

Fala aí Giancarlo, tudo bem? Olhando o seu código não vi nada de errado, sua classe de erro parece ester implementada corretamente. Os módulos parecem estarem certo também.

Mas, pode ser que olhando eu deixei passar algum pequeno detalhe, sugiro você compartilhar o projeto comigo. Assim eu consigo simular o problema aqui na minha máquina e vejo com mais detalhes e calma.

Para compartilhar você pode estar usando o Github ou Google Drive (zipado).

Fico no aguardo.

oi Matheus, Segue link do github pro meu projeto: https://github.com/geckel123/alurapic

Fala Gianvarlo, tudo bem? Fiz o teste no projeto e funcionou, forcei um erro aqui e ele passou no GlobalHandler.

Quais erros você diz não estar passando?

Fico no aguardo.

Um erro de http por exemplo. Deixei a API desligada e tentei acessar. O erro de http não passa pelo Handler.

Fala ai Giancarlo, tudo bem? Os erros do http também passam pelo GlobalErrorHandler.

Eu comentei todo código do seu metódo handleError e deixie apenas assim:

handleError(error: any): void {
        console.log("Passou no handleError");
        console.log(error.message);
}

Depois criei uma função no auth.service.ts chamada unknown:

unknow() {
    return this.http.get('http://some-unknown.address');
}

Que simplesmente vai chamar uma API que não existe.

E dentro do ngOnInit do seu signin.component.ts eu chamei essa função:

ngOnInit(): void {
        this.activatedRoute
            .queryParams
            .subscribe(params => this.fromUrl = params['fromUrl']);
        this.loginForm = this.formBuilder.group({
            userName: ['', Validators.required],
            password: ['', Validators.required]
        });
        this.platformDetectorService.isPlatformBrowser() &&
        this.userNameInput.nativeElement.focus();

    // adicionei ela aqui no final...
        this.authService.unknow().subscribe(console.log);
}

E no console do navegador, chamou e logou certinho:

Global error handler em ação

Pelo que eu reparei, parece dar algum problema no StackTrace, por isso, deixei apenas logs no handleError (assim garantimos que o mesmo está funcionando).

Espero ter ajudado.

Você tem razão neste projeto está funcionando, porém estou trabalhando em outro projeto onde estou tentando usar a mesma coisa do mesmo jeito e fiz o teste conforme você fez e não passou pelo handleError. Você poderia dar uma olhada nesse projeto? Não entendo porque num funciona e no outro não. https://github.com/geckel123/meu-projeto-angular

Bom dia, eu continuo empacado neste erro, alguém poderia me ajudar?

solução

Fala ai Giancarlo, tudo bem? Desculpa, eu não tinha visto sua resposta.

Para resolver o problema, você precisa importar o ErrorsModule depois do BrowserAnimationsModule dentro do app.module.ts.

O motivo? Não sei te dizer.

Acho que pelo fato do BrowserAnimationsModule exportar junto o BrowserModule com algumas adições na de provedores na injeção de dependência.

Provavelmente essas adições podem incluir o ErrorHandler e sem elas o Angular não consegue injetá-lo.

Espero ter ajudado.

Muito bom. Resolveu meu problema aqui. Mas Matheus, como foi que você descobriu o problema? Acho que eu nunca ia achar esse problema sozinho.

Vivência Giancarlo kkk

Ja mexo com front-end há algum tempo, sendo assim, eu já peguei problemas desse tipo, onde a ordem das coisas influenciam no funcionamento.

Basicamente fui vendo o código e testando as possíveis soluções, quando troquei a ordem dos imports funcionou.

Abraços e bons estudos.