Angular2错误处理最佳实践

3

我有一个关于Angular2错误处理最佳实践的问题。这是我用来捕获错误的代码:

Getdata(data: object){

        let body = JSON.stringify(data);
        let headers = new Headers({ 'Content-Type': 'application/json' });

        return this.http.post('/getData', body)
            .map((res) => res.json())
            .catch(this._errorHandler);
    }

  _errorHandler(error: Response){
        console.log("Error Dataservice", error);
        return Observable.throw(error || "Server Error");
    }

我需要为每个新方法编写一个catch代码块吗?还是总是可以使用_errorHandler?

谢谢!


这实际上取决于您对功能的优先级。例如:如果用户执行任何操作并且出现错误,我们应该始终记录此用户错误。更多信息请参见此处https://dev59.com/xaLia4cB1Zd3GeqPo89x#44695829。 - mayur
@mayur那么我在catch方法中总是要使用另一个函数吗? - user3356007
我认为这并不是必要的。创建一个后端服务并记录错误以进行跟踪。可以从我分享的网址 https://dev59.com/xaLia4cB1Zd3GeqPo89x#44695829 进行检查,其中包含记录和错误的服务示例。 - mayur
@mayur,问题是我每隔2分钟就会发布一篇文章。现在当我遇到特定的错误时,我想要触发组件中的一个函数。因此,我认为我需要为每个帖子制作不同的catcht,以便它们不能互相覆盖。你认为呢? - user3356007
哦,是的,我认为你可以使用通用错误处理程序来解决这个问题,而不是让它变得更加复杂。 - mayur
2个回答

11

服务中的捕获块和组件中的订阅错误回调

随着我的项目发展,这是我所采用的方式。在服务中,捕获块负责转换错误。在组件中的错误回调则负责更新任何视图逻辑。

服务

我很少能从API中以所需格式返回需要的数据,因此我通过.map()方法在其中转换数据。然后我将一个捕获块附加到该序列中。

// Service Class
getTableData(): Observable<Table>{
    return this.http.get('url')
        .map(res => {
            // transform data as needed
            return transformedData;
        }
        .catch(err => {
            // transform error as needed
            let transformedError = GlobalFunction.transformError(err);

            return Observable.throw(transformedError);
        }
}

现在当错误发生时,我会执行任何变换。例如,我可能调用一个全局方法,将错误转换为用户友好的响应。

// GlobalFunction Class
transformError(err){
   switch(err.status){
   case 404:
       return {
           status: err.status,
           message: 'Oops, it looks like that resource was not found'
       }
       break;
   }
}

组件

现在在我的组件中,我订阅了这个序列

// Component Class
ngOnInit(){
    this.loading = true;
    this.error = false;

    this.subscription = this.service.getTableData().subscribe(
        res => {
            this.table = res;
            this.loading = false;
        },
        err => {
            this.message = err.message;
            this.error = true;
            this.loading = false;
        }
     );
}

通过将所有的数据转换都包含在服务中,我保持了视图逻辑的简洁性和精炼性。我相信这种方法将组件分离开来。服务提供数据,而组件更新视图。


6

仅在组件中捕获异常

这是我在项目中使用的方法,很有效。服务从不使用 try-catch 块。每个方法都返回一个流,所有参数都是流。catch 块放置在组件内,并采取适当的措施。

异常

有一些例外情况需要在中间进行异常处理。

  • 获取身份验证令牌时出错,请处理错误并重定向到登录页面。
  • 执行多个调用时出错,请撤消更改。

我很少在中途处理错误。大部分时间,流始于组件,结束于组件,错误处理也在组件内完成。

示例

所有以 $ 结尾的参数均为流。

组件:

public error = false;
public errorMessage = '';
public users$; 

constructor(private router: Router, private _userService: UserService){
    const userId$ = this.router.params.map(params => params['id']);
    this.users$ = this._userService.getUsers$(userId$)
        .catch(error => {
           this.error = true;
           //translate error into user friendly language
           this.errorMessage = error;
        });
}

HTML

<ul *ngIf="!error"> 
 <li *ngFor="let user of users$ | async " >{{user.name}}</li>
</ul>

用户服务

public getUsers$(userId$: Observable<string>): Observable<User[]>{
    return userId$.flatMap(
      userId => this.authService.getAuthToken$()
                    .flatMap(
                       authToken => this.http.get('url', {userId})
                                         .map(res => res.json())
   ); 
}

AuthService将有一个catch块,如果未找到authtoken或会话过期或任何原因,则重定向用户到登录页面。对于所有错误,组件中的catch块都需要被执行。
我刚刚举了这个例子,如果有任何错误,请让我知道。

你能添加一个例子吗? - user3356007
@user3356007 你有检查过这个例子吗? - Vamshi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接