当前位置: 首页 > news >正文

React编程高级主题:错误处理(Error Handling)

在这里插入图片描述

文章目录

    • **5.2 错误处理(Error Handling)概述**
    • **5.2.1 `onErrorReturn` / `onErrorResume`(错误回退)**
      • **1. `onErrorReturn`:提供默认值**
      • **2. `onErrorResume`:切换备用数据流**
    • **5.2.2 `retry` / `retryWhen`(错误重试)**
      • **1. `retry`:固定次数重试**
      • **2. `retryWhen`:高级条件重试**
    • **5.3 错误处理策略对比**
    • **5.4 总结**
      • **错误回退(Fallback)**
      • **错误重试(Retry)**
      • **最佳实践**

在这里插入图片描述

5.2 错误处理(Error Handling)概述

React + RxJS/Reactive Programming 生态中,数据流(Stream)可能会因 网络错误、API 异常、数据处理失败 等原因抛出错误。如果未正确处理,错误可能导致整个数据流终止,影响用户体验。

错误处理的核心目标

  1. 防止错误导致整个应用崩溃(Graceful Degradation)。
  2. 提供合理的错误恢复机制(Retry/Fallback)。
  3. 记录错误信息(Logging & Monitoring)。

React 生态中常见的错误处理方式包括:

  • onErrorReturn / onErrorResume(错误回退)
  • retry / retryWhen(错误重试)

接下来,我们将深入探讨这些方法的 原理、实现方式及适用场景


在这里插入图片描述

5.2.1 onErrorReturn / onErrorResume(错误回退)

1. onErrorReturn:提供默认值

核心思想:当数据流发生错误时,返回一个 默认值 替代错误,使流继续执行。

适用场景

  • 适用于 可预测的错误(如 API 404 返回默认数据)。
  • 不希望错误中断数据流,但可以接受降级数据。

示例(RxJS)

import { of, throwError } from 'rxjs';
import { onErrorReturn } from 'rxjs/operators';

const source$ = throwError(new Error('API Failed')); // 模拟错误

source$
  .pipe(
    onErrorReturn(() => ({ data: 'Default Value' })) // 错误时返回默认值
  )
  .subscribe({
    next: (val) => console.log('Received:', val), // 输出: Received: { data: 'Default Value' }
    error: (err) => console.error('Error:', err), // 不会触发
  });

底层原理

  • onErrorReturn 会在 error 发生时拦截错误,并调用回调函数返回一个默认值。
  • 该操作符会 终止原 Observable,并返回一个新的 Observable,发射默认值后 complete

在这里插入图片描述

2. onErrorResume:切换备用数据流

核心思想:当主数据流失败时,切换到备用数据流(Fallback Stream)。

适用场景

  • 主 API 失败时,回退到缓存/备用 API。
  • 多数据源冗余设计(如 CDN 回源)。

示例(RxJS)

import { of, throwError } from 'rxjs';
import { onErrorResumeWith } from 'rxjs/operators';

const mainApi$ = throwError(new Error('Main API Down'));
const fallbackApi$ = of({ data: 'Fallback Data' });

mainApi$
  .pipe(
    onErrorResumeWith(fallbackApi$) // 主API失败时切换到备用流
  )
  .subscribe({
    next: (val) => console.log('Received:', val), // 输出: Received: { data: 'Fallback Data' }
    error: (err) => console.error('Error:', err), // 不会触发
  });

底层原理

  • onErrorResumeWith 会在错误发生时 取消订阅原 Observable,并立即订阅备用 Observable。
  • 如果备用流也失败,错误会继续传播(除非嵌套使用多个 onErrorResumeWith)。

在这里插入图片描述

5.2.2 retry / retryWhen(错误重试)

1. retry:固定次数重试

核心思想:在发生错误时,自动重新订阅数据流(可设定最大重试次数)。

适用场景

  • 临时性错误(如网络抖动、API 限流)。
  • 需要 简单重试逻辑 的场景。

示例(RxJS)

import { throwError, timer } from 'rxjs';
import { retry } from 'rxjs/operators';

let attempts = 0;
const flakyApi$ = new Observable((subscriber) => {
  attempts++;
  if (attempts < 3) {
    subscriber.error(new Error('API Failed')); // 前两次模拟失败
  } else {
    subscriber.next('Success on attempt ' + attempts);
    subscriber.complete();
  }
});

flakyApi$
  .pipe(
    retry(2) // 最多重试2次(共3次尝试)
  )
  .subscribe({
    next: (val) => console.log('Received:', val), // 输出: Received: Success on attempt 3
    error: (err) => console.error('Error:', err), // 如果第3次仍失败,会触发
  });

底层原理

  • retry(n) 会在每次错误时重新订阅源 Observable,最多 n 次。
  • 如果所有重试均失败,错误会传递给 Subscriber

在这里插入图片描述

2. retryWhen:高级条件重试

核心思想:通过 自定义逻辑控制重试策略(如指数退避、依赖条件重试)。

适用场景

  • 复杂重试策略(如指数退避、Token 刷新后重试)。
  • 需要 动态调整重试行为(如根据错误类型决定是否重试)。

示例(RxJS:指数退避)

import { throwError, timer } from 'rxjs';
import { retryWhen, mergeMap, delay } from 'rxjs/operators';

const flakyApi$ = throwError(new Error('API Failed'));

flakyApi$
  .pipe(
    retryWhen((errors) =>
      errors.pipe(
        mergeMap((err, attempt) => {
          if (attempt >= 3) {
            return throwError(err); // 超过3次后放弃
          }
          const delayMs = 1000 * 2 ** attempt; // 指数退避:1s, 2s, 4s...
          console.log(`Retry in ${delayMs}ms`);
          return timer(delayMs); // 延迟后重试
        })
      )
    )
  )
  .subscribe({
    next: (val) => console.log('Received:', val),
    error: (err) => console.error('Final Error:', err), // 输出: Final Error: Error: API Failed
  });

在这里插入图片描述
底层原理

  1. retryWhen 接收一个 Observable<Error>,允许自定义重试逻辑。
  2. 每次错误时,可以:
    • 返回 Observable 延迟重试(如 timer)。
    • 返回 throwError 终止重试。
  3. 适用于 Token 刷新后重试
    retryWhen((errors) =>
      errors.pipe(
        mergeMap((err) => {
          if (isTokenExpired(err)) {
            return refreshToken().pipe( // 先刷新Token
              mergeMap(() => timer(1000)) // 再延迟重试
            );
          }
          return throwError(err); // 非Token错误直接抛出
        })
      )
    )
    

在这里插入图片描述

5.3 错误处理策略对比

方法适用场景优点缺点
onErrorReturn提供默认值(如空数据、占位图)简单易用,确保流不中断无法恢复真实数据
onErrorResume切换到备用数据源(如缓存/冗余API)支持多数据源冗余备用数据可能不一致
retry临时性错误(如网络抖动)自动重试,减少手动处理可能加重服务器负载(无限重试时)
retryWhen复杂重试逻辑(如指数退避、Token刷新)灵活控制重试策略实现复杂度较高

5.4 总结

错误回退(Fallback)

  • onErrorReturn:适合静态降级(如默认值)。
  • onErrorResume:适合动态降级(如备用API)。

错误重试(Retry)

  • retry(n):适合简单重试(固定次数)。
  • retryWhen:适合高级策略(指数退避、条件重试)。
    在这里插入图片描述

最佳实践

  1. 关键数据:优先使用 retryWhen + onErrorResume 保证可用性。
  2. 非关键数据:使用 onErrorReturn 快速降级。
  3. 监控所有错误:在 subscribeerror 回调中记录日志。

通过合理组合这些策略,可以构建 健壮、可恢复的 React 数据流应用

相关文章:

  • 网站系统繁忙seo对网店推广的作用
  • 和田知名网站建设企业如何自己开发网站
  • seo教程从零开始seo推广学院
  • 怎么做网站的学校的大图培训机构网站设计
  • 专业的网站设计建设百度如何快速收录网站
  • h5做的分销网站搜狗网页搜索
  • ts基础知识总结
  • Java后端开发流程
  • [ctfshow web入门]burpsuite的下载与使用
  • 每日c/c++题 备战蓝桥杯(小球反弹)[运动分解求解,最大公约数gcd]
  • Java进阶之旅-day05:网络编程
  • 1-SQL server 2022和SSMS的使用案例1
  • 从零构建大语言模型全栈开发指南:附录与资源-2.数据集大全-公开语料库、多模态数据集与领域专用数据源
  • 构建第一个ArkTS应用:Hello World之旅
  • 【百日精通JAVA | SQL篇 | 第三篇】 MYSQL增删改查
  • scala课后总结(5)
  • matlab 计算点云的形心
  • Flask学习笔记 - 项目结构 + 路由
  • C++11观察者模式示例
  • C语言单链表的增删改补
  • 从制造业历史来看,汽车兴,则制造业兴,则国兴,则机器视觉兴
  • 云原生与微服务的关系
  • Git 换行符警告(LF replaced by CRLF)的解决方案
  • 【无人机】PX4 飞控系统架构
  • 【Scratch编程系列】Scratch编程软件界面
  • b4a安卓开发技术和建议,VB6开发Android APK