在我们的前端开发中,请求出现错误是比较常见的情况,假设我们正在使用 RxJS 实现异步操作的话,那么在实际的开发中要如何处理这些错误呢?本文将讨论 RxJS 的错误处理方式,重点介绍重试和重定向,希望能够帮助各位读者掌握更加完善的错误处理技能。
RxJS 的错误处理
RxJS 是一个基于可观察对象的库,它可以极大地简化处理异步操作的流程。然而,在实际的开发过程中,我们可能会遇到各种意外的错误,如请求失败、网络出现错误等,这些错误无疑会影响我们的程序。对于这些错误,RxJS 提供了多种方法来处理它们。
RxJS 错误处理的方法很多,如 catchError、retry、retryWhen 等,我们需要理解不同方法的区别并根据业务需求去选择不同的操作方式。
catchError
catchError 可以捕捉 Observable 中发生的错误,并返回一个备用 Observable。该方法包装了一个源 Observable,如果源 Observable 发出了错误通知,catchError 就会寻找可插入的备用 Observable,如果找到了就使用备用 Observable,并且重新订阅它,如果没有找到,会直接返回 error 通知,并且终止 Observable 的执行。
// javascriptcn.com 代码示例 import { Observable, of, throwError } from 'rxjs' import { catchError } from 'rxjs/operators' const observable = new Observable((observer) => { observer.next(1); observer.next(2); observer.error('Network error!'); observer.complete(); }); observable.pipe( catchError((error) => { console.log(error); return of(2, 3, 4); }) ).subscribe((value) => { console.log(value); });
在上述代码中,我们创建了一个 Observable 对象,它会先发出两个 next 通知,紧接着会出现一个错误的 error 通知,最后是一个 complete 通知。然后我们在 pipe 操作符中调用了 catchError,来处理这个错误。catchError 会捕捉到这个错误,并返回后面的 of(2, 3, 4),这个新的 Observable 对象会重新订阅并发出 2、3、4 三个值。
retry
retry 会在遇到错误时,会重新订阅源 Observable n 次,直到发出正确的值。这种情况下如果一直不发出正常的值,那么这个 Observable 就会一直重试下去。
// javascriptcn.com 代码示例 import { interval, throwError } from 'rxjs'; import { take, mergeMap, retry } from 'rxjs/operators'; const source = interval(1000).pipe( mergeMap((value) => { if (value > 3) { return throwError('Error!'); } return of(value); }), retry(2) ); source.subscribe({ next: (value) => console.log(value), error: (err) => console.error(err), complete: () => console.log('Complete!'), });
在上述代码中,我们创建了一个 interval Observable,它每间隔 1 秒会发出一个值。另外,我们还创建了一个 mergeMap 操作符,它接收一个参数 value,如果 value 的值大于 3,那么就会触发一个错误。于是我们在 retry 操作符中设置了重试的次数为 2,当发生错误后,源 Observable 就会重新订阅,并重新接收值,直到不发生错误或者重试次数达到上限为止。
retryWhen
retryWhen 与 retry 的功能类似,但是我们可以在 retryWhen 中自定义重试策略。通过传递一个存有错误对象的 observable,我们可以对 retry 的次数进行控制。
// javascriptcn.com 代码示例 import { interval, of, throwError } from 'rxjs'; import { mergeMap, retryWhen, delay } from 'rxjs/operators'; const source = interval(1000).pipe( mergeMap((value) => { if (value > 3) { return throwError('Error!'); } return of(value); }), retryWhen((errors) => errors.pipe(delay(3000))) ); source.subscribe({ next: (value) => console.log(value), error: (err) => console.error(err), complete: () => console.log('Complete!'), });
在上述代码中,我们创建了一个 interval Observable,并创建了 mergeMap 操作符来模拟一个可能会发生错误的操作。如果值大于 3,那么就会触发一个错误。然后我们在 retryWhen 操作符中添加了一个延迟操作 delay,它能够延迟发送通知的时间,这个操作符的作用是等待一段时间后再次尝试订阅源 Observable。(这里的意图是:在某些情况下,立刻重试可能会导致错误的再次发生,因此我们需要等待一段时间,确保源 Observable 已经恢复了状态,然后再尝试重试。)
重定向
RxJS 还提供了一种错误处理方式,称为重定向。当发生错误时,可以将流导向一个备用 Observable,还可以在备用 Observable 中自定义处理方式。下面我们将分别讨论重定向的多种方法。
switchMap 和 catchError 结合使用
// javascriptcn.com 代码示例 import { from, of } from 'rxjs'; import { catchError, switchMap } from 'rxjs/operators'; import axios from 'axios'; const urls = ['https://api.github.com/users?since=135', 'https://api.github.com/users?since=101']; from(urls) .pipe( switchMap((url) => axios.get(url)), catchError(() => of({ response: 'fallback response' })) ) .subscribe({ next: (value) => console.log(value), error: (err) => console.error(err), complete: () => console.log('Complete!'), });
在上述代码中,我们首先创建了一个包含两个 url 的数组,然后我们用 from 操作符把它转换为一个 Observable 对象。接着使用 switchMap 操作符来获取 url 中指定的内容,如果出现一个错误,那么就会转向到 catchError 操作符中去找一个备用的 Observable。
retry 与 catchError 结合使用
// javascriptcn.com 代码示例 import { from, throwError } from 'rxjs'; import { catchError, retry } from 'rxjs/operators'; import axios from 'axios'; const urls = ['https://api.github.com/users?since=135', 'https://api.github.com/users?since=101']; from(urls) .pipe( retry(3), catchError((error) => { console.log(error); return throwError('Network Errors!'); }), switchMap((url) => axios.get(url)) ) .subscribe({ next: (value) => console.log(value), error: (err) => console.error('Error: ', err), complete: () => console.log('Complete!'), });
在上述代码中,我们使用了 retry 和 catchError 两个操作符,并将它们和 axios 请求结合使用。retry 操作符会在源 Observable 发生错误时,重新订阅它,最多尝试三次重新获取请求的数据。如果这些重试都失败了,catchError 操作符就会发送一个错误通知,这个错误通知最终被 combineLatest 操作符订阅,然后就形成了一个新的 Observable。
fallback 备用请求
// javascriptcn.com 代码示例 import { from, of, throwError } from 'rxjs'; import { switchMap, catchError } from 'rxjs/operators'; import axios from 'axios'; const urls = ['https://api.github.com/users', 'https://api.github.com/userssd']; from(urls) .pipe( switchMap((url) => axios.get(url)), catchError(() => { console.log('catch error'); return of({ data: [{ id: 0, login: 'Fallback User' }] }); }) ) .subscribe((value) => { console.log(value); });
在上面的代码中,我们先尝试获取第一个 url 的数据,如果发生错误,就会转向到 catchError 操作符中。在这个操作符中返回备用的 Observable,它会发送一条带有 fallbackUser 数据的通知。
总结
在本文中,我们讨论了 RxJS 的错误处理方式,包括 catchError、retry、retryWhen 和重定向方式,我们还提供了代码示例来让读者更好地理解这些方法的使用。请务必根据自己的业务需求选择适合的错误处理方法,以确保程序的正确执行。希望这篇文章能给读者带来一些指导和帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6534d4bc7d4982a6eba2881b