为什么全局错误处理程序中的烤面包机服务在Angular4 / 5/6中不起作用?

时间:2018-07-20 13:47:17

标签: angular typescript http-status-code-401 zone angular2-toaster

我的要求是在应用程序组件加载之前通过调用两个Rest Api加载一些数据。如果API出现任何错误,则会在Toaster(angular2-toaster)中显示消息。

在加载应用程序组件之前,将执行以下AppLoadService

EF_MIPS_NAN2008 -mnan=2008

我的App模块文件如下所示

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/toPromise';
import { APP_SETTINGS } from 'app/app-settings/settings';

@Injectable()
export class AppLoadService {

constructor(private httpClient: HttpClient) { }

loadLabs(): Promise<any> {
    return new Promise((resolve, reject) => {
        this.httpClient.get(`/api/v1/api/lab`)
            .toPromise()
            .then((res: any) => {
                APP_SETTINGS.labs = res;
                resolve();
            })
            .catch((err: any) => {
                reject(err);
            });
    });
}
/////////////////******************////////////////////////////
getSettings(): Promise<any> {
    return new Promise((resolve, reject) => {
        this.httpClient.get(`assets/settings/config.json`)
            .toPromise()
            .then((config: any) => {
                APP_SETTINGS.loginURL = config["login"];
                console.log(`config.json loaded:: `, APP_SETTINGS);
                resolve();
            })
            .catch((err: any) => {
                reject(err);
            });
    });
 }

GlobalErrorHandler.ts

    export function createTranslateLoader(http: Http) {
        return new TranslateStaticLoader(http, './assets/i18n', '.json');
    }


    @NgModule({
    declarations: [
        AppComponent, CustomDateRangePickerComponent
    ],
    imports:  [
            // coreModules: //
            BrowserModule,
            BrowserAnimationsModule,
            ToasterModule,
            HttpClientModule,
            FormsModule,
            CommonModule, //<====added

            //thirdPartyModules:
            // ToastyModule,
            BootstrapModalModule,
            //appModules: //
            AppRoutingModule,
            FooterModule,
            ErrorModule,
            AccessDeniedModule,
            NotFoundModule,
            AppLoadModule, //Startupdata before APP loaded
            RouterModule.forRoot([]),
            TranslateModule.forRoot({ provide: TranslateLoader, useFactory: (createTranslateLoader), deps: [Http] })
    ],
    providers: [
        ToasterService,
        StartupService,
        ResponseStatusesService,
        LocalStorageService,
        ApplicationSettingsService,
        LabSelectionService,
        AccountService,
        AuthService,
        AlertService,
        AuthGuard,
        RolesGuard,
        FeaturebasedGuard,
        ErrorLogService,
        {
            provide: ErrorHandler,
            useClass: GlobalErrorsHandler
        },
        {
            provide: HTTP_INTERCEPTORS,
            useClass: AppHttpInterceptor,
            multi: true
        },
        {
            provide: LocationStrategy,
            useClass: HashLocationStrategy
        },
    ],
    exports: [TranslateModule],
    bootstrap: [AppComponent]
    })

    export class AppModule { }

AppComponent.html

@Injectable()
export class GlobalErrorsHandler extends ErrorHandler {
constructor(
    private injector: Injector,
    private errorLogService: ErrorLogService

) {
    super();
    alert('GlobalErrorsHandler');

}
handleError(error: Error | HttpErrorResponse) {
    debugger;
    let toaster = this.injector.get(ToasterService);
    toaster.pop("head", "body");
}
}

拦截器也有问题

<toaster-container [toasterconfig]="ang2toasterconfig"></toaster-container>

<router-outlet></router-outlet>

据我所知,toaster.pop('','')方法是在装载烤面包机容器之前调用的。如何解决这个问题。根组件是App组件,我在其中放置了烤面包机容器。请向我建议解决此问题的体系结构。

还有一个地方,我需要处理不同的错误...在本地错误处理程序(组件级别)中还是在全局错误处理程序中或在拦截器中?

错误示例:400,404,500+ ...等

  

Update1:​​按照David注释更改的代码,如下所示,但控制台中仍未显示任何容器.....消息,并且看不到烤面包机

使用“ angular2-toaster”:“ ^ 6.1.0”

enter image description here

enter image description here

这些API调用将在应用程序组件之前触发 enter image description here

enter image description here

5 个答案:

答案 0 :(得分:3)

这是angular2-toaster自述文件中的documented,因为它发生的次数及其引起的混乱。

这是由于Angular如何在错误处理程序中处理UI调度(或者缺少它)造成的。

  

执行的handleError函数超出了Angular区域的大小。您需要明确告知Angular在区域上下文中运行pop调用。

export class AppErrorHandler implements ErrorHandler {
    constructor(
        private toasterService: ToasterService,
        private ngZone : NgZone) { }

    handleError(error: any): void {
        this.ngZone.run(() => {
            this.toasterService.pop('error', "Error", error);
        });  
    }
}

答案 1 :(得分:2)

我添加了Java Script Toaster,但没有显示角度,并显示了Text。

答案 2 :(得分:1)

之所以会这样,是因为handleError()方法是在 Angular区域之外执行的。由于未在其上进行更改检测,因此这会导致烤面包无法正常工作。在错误处理程序中打开onActivateTick,以确保吐司在Angular的区域内运行:

工作示例

@Injectable()
export class GlobalErrorHandler extends ErrorHandler {

    constructor(@Inject(Injector) private readonly injector: Injector) {}

    handleError(error) {
        console.log("Handling error: " + error);
        this.toastrService.error("testing", null, { onActivateTick: true })
    }

    /**
     * Need to get ToastrService from injector rather than constructor injection to avoid cyclic dependency error
     * @returns {} 
     */
    private get toastrService(): ToastrService {
        return this.injector.get(ToastrService);
    }

}

Git Issue

答案 3 :(得分:0)

客户错误处理程序将在tosterservice之前创建为 但是在创建错误处理程序时,名册服务不可用

要解决此问题,请在自定义错误处理程序的构造函数中使用Injector,并在handleerror方法中使用使用注射器的tosterservice

答案 4 :(得分:0)

这是Angular 6中的示例作品

app.component.html

<toaster-container [toasterconfig]="toasterconfig"></toaster-container>
<router-outlet></router-outlet>

app.component.ts

import { ToasterConfig } from 'angular2-toaster';
import { CustomToasterService} from '../app/core/_services/custom-toaster.service';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
    providers: [CustomToasterService],
})
export class AppComponent implements OnInit {
    toasterConfig: any;
    toasterconfig: ToasterConfig = new ToasterConfig({
        positionClass: 'toast-bottom-right',
        showCloseButton: true,
        tapToDismiss: false,
        timeout: 5000
    });
    constructor(public settings: SettingsService) {
    }

custom-toaster.service.ts

import { Injectable } from '@angular/core';
import { ToasterService } from 'angular2-toaster';

@Injectable()
export class TooasterService {
    constructor(
        private toasterService: ToasterService,
    ) { }


    public showError(error) {
        this.toasterService.pop('error', error.name, error.Message); 
    }
}