使用 Angular HttpClient 服务处理异常
介绍
HTTP 请求极易出错,因为它们周围通常有很多未知因素。您尝试访问的服务器是否正常运行?API 是否返回了您期望的有效负载?在本指南中,您将了解当这些问题没有得到适当回答时该怎么办。我们将讨论在使用 Angular 的 HttpClient 服务时管理应用内 HTTP 异常的一些最佳方法。
开始处理 HTTP 异常
当谈到在 Angular 中处理 HTTP 异常时,几乎不可能不谈论 RxJs。Angular 框架大量采用了 RxJs 库 - 该库将响应式编程引入了 JavaScript 生态系统。Angular 自己的 HttpClient 在底层使用了 RxJs 来确保客户端具有可观察的 API。
为了正确处理异常,您需要熟悉一些 RxJs 运算符。本指南中我们将关注的主要运算符是 catchError和throwError运算符。
捕获 HTTP 异常
使用catchError运算符可以捕获可观察流中可能发生的错误。让我们看看如何在示例应用中使用此运算符。
以下是从服务器获取书籍的示例服务。它看起来像这样:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Book } from 'app/models/book';
@Injectable()
export class BooksService {
private booksApiUrl = '/api/books';
constructor(private http: HttpClient) { }
getBooks(): Observable<Book[]> {
return this.http.get(this.booksApiUrl);
}
}
下面是一个使用BooksService的示例组件:
import { Component } from '@angular/core';
import { BooksService } from 'app/services/books';
import { Book } from 'app/models/book';
@Component({
selector: 'app-books',
template: `
<ul *ngFor="let book of books$">
<li>{{ book.title }}</li>
</ul>
`
})
export class BooksComponent {
books$: Observable<Book[]>;
constructor(private booksService: BooksService) {
this.books$ = this.booksService.getBooks();
}
}
上面,BooksComponent与BooksService通信,以便从服务器获取书籍负载。如果在此请求期间出现问题怎么办?当然,您需要以某种方式处理此异常。
接下来,将catchError操作符添加到BooksComponent来处理异常:
import { Component } from '@angular/core';
import { BooksService } from 'app/services/books';
import { Book } from 'app/models/book';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';
@Component({
selector: 'app-books',
template: `
<error-alert *ngIf="errorMsg" [msg]="errorMsg"></error-alert>
<ul *ngFor="let book of books$">
<li>{{ book.title }}</li>
</ul>
`
})
export class BooksComponent {
books$: Observable<Book[]>;
errorMsg: string;
constructor(private booksService: BooksService) {
this.books$ =
this.booksService
.getBooks()
.pipe(
catchError(error => {
if (error.error instanceof ErrorEvent) {
this.errorMsg = `Error: ${error.error.message}`;
} else {
this.errorMsg = `Error: ${error.message}`;
}
return of([]);
})
);
}
}
您已修改BooksComponent以捕获 HTTP 请求中可能发生的任何异常!您还使用了可观察对象辅助函数来确保当发生错误时,可观察对象返回一个空数组。现在,当发生错误时,用户可以轻松看到消息。
但是,如果你想对显示的错误消息进行更多的自定义控制,该怎么办?在下一节中,你将学习如何使用throwError运算符来实现这一点。
重新抛出 HTTP 异常
很可能,当发生异常时,您不想向用户显示从 Angular HttpClient 获得的确切错误消息。自定义此消息的一个好方法是使用throwError抛出您自己的自定义异常。首先,更新您的BooksService以根据 HTTP 请求的最终状态抛出自定义错误。
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Book } from 'app/models/book';
import { catchError, throwError } from 'rxjs/operators';
@Injectable()
export class BooksService {
private booksApiUrl = '/api/books';
constructor(private http: HttpClient) { }
getBooks(): Observable<Book[]> {
return this.http
.get(this.booksApiUrl)
.pipe(
catchError(error => {
let errorMsg: string;
if (error.error instanceof ErrorEvent) {
this.errorMsg = `Error: ${error.error.message}`;
} else {
this.errorMsg = this.getServerErrorMessage(error);
}
return throwError(errorMsg);
})
);
}
private getServerErrorMessage(error: HttpErrorResponse): string {
switch (error.status) {
case 404: {
return `Not Found: ${error.message}`;
}
case 403: {
return `Access Denied: ${error.message}`;
}
case 500: {
return `Internal Server Error: ${error.message}`;
}
default: {
return `Unknown Server Error: ${error.message}`;
}
}
}
}
上述代码将一些错误处理逻辑从BooksComponent移至服务。通过使用throwError运算符和新的getServerErrorMessage方法,您现在可以从服务中抛出自定义错误来处理 HTTP 错误。
现在,简化你的BooksComponent。
import { Component } from '@angular/core';
import { BooksService } from 'app/services/books';
import { Book } from 'app/models/book';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';
@Component({
selector: 'app-books',
template: `
<error-alert *ngIf="errorMsg" [msg]="errorMsg"></error-alert>
<ul *ngFor="let book of books$">
<li>{{ book.title }}</li>
</ul>
`
})
export class BooksComponent {
books$: Observable<Book[]>;
errorMsg: string;
constructor(private booksService: BooksService) {
this.books$ =
this.booksService
.getBooks()
.pipe(
catchError(error => {
this.errorMsg = error.message;
return of([]);
})
);
}
}
最佳实践是让组件尽可能简单。在本例中,您能够适当地将错误处理逻辑从BooksComponent移至BooksService。
结论
在本指南中,您学习了如何管理应用中的 HTTP 异常。您已经了解了如何使用 RxJs catchError运算符来捕获使用 Angular HttpClientservice 时发生的任何 HTTP 异常。您还了解了如何使用 RxJs throwError运算符有意抛出自己的错误或重新抛出捕获的错误。通过使用这两种技术,您可以很好地处理任何 HTTP 驱动的应用程序中出现的意外错误。
了解更多
探索 Pluralsight 的这些 Angular 和 HTTP 课程以继续学习:
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~