10

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

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

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);
            });
    });
 }

我的 App 模块文件如下所示

    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 { }

GlobalErrorHandler.ts

@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");
}
}

应用组件.html

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

<router-outlet></router-outlet>

拦截器也有同样的问题

            import { Injectable, Injector } from '@angular/core';
            import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
            import { Observable } from 'rxjs/Observable';
            import 'rxjs/add/operator/do';
            import 'rxjs/add/operator/catch';
            import 'rxjs/add/observable/throw';
            import { ToasterService } from 'angular2-toaster';
            import { AuthService } from 'app/blocks/auth/auth.service';
            import { TranslateService } from 'ng2-translate';
            import { AlertService } from '../../core/services/common';


            @Injectable()
            export class AppHttpInterceptor implements HttpInterceptor {

                constructor(private injector: Injector) { }

                intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
                    debugger;
                    console.log(req);
                    if (!window.navigator.onLine) { // check to see if there's internet
                        // if there is no internet, throw a HttpErrorResponse error
                        // since an error is thrown, the function will terminate here
                        return Observable.throw(new HttpErrorResponse({ error: 'NO_INTERNET' }));
                    } else {
                        // else return the normal request
                        return this.handleResponse(next, req);
                    }


                }
                handleResponse(next, req) {
                    return next.handle(req)
                        .do((ev: HttpEvent<any>) => {
                            if (ev instanceof HttpResponse) {
                            }
                        })
                        .catch((response: any) => {
                            if (response instanceof HttpErrorResponse) {
                                console.log('response in the catch: ', response);
                                this.handleReponseExceptions(response);
                            }
                            return Observable.throw(response);
                        });
                }
                handleReponseExceptions(exception) {
                    let toaster = this.injector.get(ToasterService);
                    let translate = this.injector.get(TranslateService);

                    // TOASTER NOT WORKING AND TRANSLATE NOT WORKING
                    toaster.pop("test","test");

                    this.translate.get(["test", "test"]).subscribe(res => {
                        //NOT FETCHING FROM en.json
                    });

                }

            }

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

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

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

更新1:根据大卫评论更改代码如下,但仍然没有容器.....消息在控制台中出现,没有烤面包机可见

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

在此处输入图像描述

在此处输入图像描述

这些是将在应用组件之前触发的 API 调用 在此处输入图像描述

在此处输入图像描述

4

5 回答 5

10

由于这种情况发生的次数及其引起的混乱,这在's README 中有记录。angular2-toaster

这是由 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);
        });  
    }
}
于 2018-07-20T14:59:33.877 回答
2

我添加了 Java Script Toaster not angular 并显示了文本。

于 2018-07-25T09:47:19.713 回答
1

发生这种情况是因为handleError()方法是在Angular zone之外执行的。这会导致 toast 无法正常运行,因为没有在其上运行更改检测。在错误处理程序中打开onActivateTick以确保 toast 在 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问题

于 2019-09-08T05:34:24.977 回答
0

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

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

于 2018-07-20T16:13:43.487 回答
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) {
    }

定制烤面包机.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); 
    }
}
于 2018-08-28T10:54:54.423 回答