简体   繁体   English

在 catchError RxJs 6 中调用全局 handleError function(从 RxJs 5 迁移)

[英]Calling global handleError function inside catchError RxJs 6 (Migrating from RxJs 5)

Recently I upgraded my Ionic 3 project to Ionic 4, with this upgrade a several other packages were updated as well (Angular 5 --> 8 and RxJs 5.5 --> 6.5).最近我将我的 Ionic 3 项目升级到 Ionic 4,通过这次升级还更新了其他几个包(Angular 5 --> 8 和 RxJs 5.5 --> 6.5)。 Most of the changes needed in code are going well but there is one change I cant resolve.代码中所需的大部分更改都进展顺利,但有一个更改我无法解决。

In one of my services I have a function which does an API fetch (GET).在我的一项服务中,我有一个 function 执行 API 获取(GET)。 Any errors in the fetch ( http GET ) are handled in a global error function.提取( http GET )中的任何错误都在全局错误 function 中处理。 In my old Ionic 3 / RxJs 5~ application this was done as follows:在我的旧 Ionic 3 / RxJs 5~ 应用程序中,这样做如下:

public fetch(): Observable<T[]> {
    let _path: string = this.path; 
    const url = this.getUrl(_path);

    return this.http
        .get(url, this.options)
        .catch(this.handleError);
}

The handleError function is defined in another service: handleError在另一个服务中定义:

protected handleError(error: any) {
    const errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';

    this.logger.error('API endpoint: ' + this.path, errMsg);
    this.showErrorToast(); // not async in Ionic 3

    return Observable.throw(errMsg);
}

In my Ionic 4 / RxJs 6 application I am trying to recreate this without success.在我的 Ionic 4 / RxJs 6 应用程序中,我试图重新创建它但没有成功。 I have read and changed the following:我已阅读并更改以下内容:

  • catch is deprecated and should be replaced with catchError catch已弃用,应替换为catchError
  • Observable.throw is also deprecated and should be replaced by throwError Observable.throw也已弃用,应替换为throwError

So my new implementation looks as follows:所以我的新实现如下所示:

public fetch(): Observable<T[]> {
    let _path: string = this.path; 
    const url = this.getUrl(_path);

    return this.http
        .get(url, this.options)
        .pipe(
          catchError(() => { // this line is returning a error
            this.handleError;
          }
        ));  
}

protected handleError(error: any) {
    const errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';

    this.logger.error('API endpoint: ' + this.path, errMsg);
    this.showErrorToast(); // now async in Ionic 4

    return throwError(errMsg); // Changed this 
}

However, the catchError(() => is returning the following error:但是, catchError(() =>返回以下错误:

Argument of type '() => void' is not assignable to parameter of type '(err: any, caught: Observable<Object>) => ObservableInput<any>'.
  Type 'void' is not assignable to type 'ObservableInput<any>'

After trying several other things I am a bit clueless how this could be solved, any ideas or pointers?在尝试了其他几件事之后,我有点不知道如何解决这个问题,有什么想法或指示吗?

UPDATE更新

After implementing a few of the proposed solutions I keep getting the same, but different error then the previous one:在实施了一些建议的解决方案后,我一直得到与前一个相同但不同的错误:

 Type 'Observable<Object>' is not assignable to type 'Observable<T[]>'.
      The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
        Type 'Object' is missing the following properties from type 'T[]': length, pop, push, concat, and 26 more

So after some investigation I came up with this (Using @theMayer proposed solution):所以经过一番调查,我想出了这个(使用@theMayer提出的解决方案):

I Changed:我变了:

return this.http
    .get(url, this.options)
    .pipe(
      catchError(e => {
        this.handleError(e);
        return EMPTY;
      }
    ));

to:至:

return this.http
        .get<T[]>(url, this.options)
        .pipe(
          catchError(e => {
            this.handleError(e);
            return EMPTY;
          }
        ));

Above change removes the error but I am not sure this is the way to go?以上更改消除了错误,但我不确定这是通往 go 的方法吗? The fetch function will loop over multiple other services which define the API endpoints.提取 function 将遍历定义 API 端点的多个其他服务。

You're getting tripped up by a syntax change in RxJs 6. The error message looks confusing, but all it says is that your error handler must return an observable (as all pipeable operators must).您被 RxJs 6 中的语法更改绊倒了。错误消息看起来令人困惑,但它只是说您的错误处理程序必须返回一个 observable(所有可管道操作符都必须返回)。 It doesn't care what the observable is of , however.然而,它并不关心 observable什么。

So, a simple rewrite is in order (note that EMPTY may not be exactly what you need here, but it works in my code):因此,需要进行简单的重写(请注意, EMPTY可能不是您在这里所需要的,但它在我的代码中有效):

import { EMPTY } from 'rxjs';

public fetch(): Observable<T[]> {
    let _path: string = this.path; 
    const url = this.getUrl(_path);

    return this.http
        .get(url, this.options)
        .pipe(
          catchError(e => {        // need to capture the 'e' here...
            this.handleError(e);   // pass to your function
            return EMPTY;          // and return empty
          }
        ));  
}

protected handleError(error: any) {
    const errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';

    this.logger.error('API endpoint: ' + this.path, errMsg);
    this.showErrorToast(); // now async in Ionic 4
}

Remove this:删除这个:

return throwError(errMsg);返回抛出错误(errMsg); // Changed this //改变了这个

Maybe you need to use like this:也许你需要这样使用:

.pipe(catchError(this.handleError);

If you want a general soultion for error handling you can use the Angular built-in ErrorHandler.如果你想要一个通用的错误处理方法,你可以使用 Angular 内置的 ErrorHandler。 With this you can catch all the errors occurring runtime and you can show a toaster or whatever you want.有了这个,你可以捕捉到运行时发生的所有错误,你可以展示一个烤面包机或任何你想要的东西。 If you use this approach then you dont need to implement the error catching login in all your services.如果您使用这种方法,那么您不需要在所有服务中实现错误捕获登录。 This will be automatically triggered when something failed.当某些事情失败时,这将自动触发。

In your AppModule in providers import your custom error handler service:在提供程序中的 AppModule 中,导入您的自定义错误处理程序服务:

providers: [{ provide: ErrorHandler, useClass: RuntimeErrorHandlerService }]

Custom error handling service:自定义错误处理服务:

@Injectable()
export class RuntimeErrorHandlerService implements ErrorHandler {
  constructor(private injector: Injector) {}

  handleError(error: any) {
    // Show your toaster or do whatever you want
    const toasterService = this.injector.get(ToasterService);
    toasterService.show(error);
  }
}

You can check if it is a http request error or a runtime error.您可以检查它是 http 请求错误还是运行时错误。 Angular documentation: https://angular.io/api/core/ErrorHandler Angular 文档: https://angular.io/api/core/ErrorHandler

I can see you only put function reference inside catchError(), catchError needs to return an observable.我可以看到你只将 function 引用放在 catchError() 中,catchError 需要返回一个 observable。 try this尝试这个

catchError(e => { 
            return this.handleError(e);
          }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM