RxJS 核心操作符详细用法示例

news2025/5/24 12:50:28

1. Observable 详细用法

Observable 是 RxJS 的核心概念,代表一个可观察的数据流。

创建和订阅 Observable

import { Observable } from "rxjs";

// 1. 创建Observable
const myObservable = new Observable(subscriber => {
  // 发出三个值
  subscriber.next('第一个值');
  subscriber.next('第二个值');
  subscriber.next('第三个值');
  
  // 模拟异步操作
  setTimeout(() => {
    subscriber.next('异步值');
    subscriber.complete(); // 完成流
  }, 1000);
  
  // 可选的清理逻辑
  return () => {
    console.log('Observable被取消订阅');
  };
});

// 2. 订阅Observable
const subscription = myObservable.subscribe({
  next: value => console.log('收到值:', value),
  error: err => console.error('发生错误:', err),
  complete: () => console.log('流已完成')
});

// 3. 取消订阅 (通常在组件销毁时调用)
setTimeout(() => {
  subscription.unsubscribe();
}, 2000);

/* 输出顺序:
收到值: 第一个值
收到值: 第二个值
收到值: 第三个值
(等待1秒)
收到值: 异步值
流已完成
(再等待1秒)
Observable被取消订阅
*/

2. of 操作符详细用法

of 用于创建一个会立即发出给定参数的 Observable。

基本示例

import { of } from "rxjs";

// 发出固定值
of('苹果', '香蕉', '橙子').subscribe({
  next: fruit => console.log('水果:', fruit),
  complete: () => console.log('水果列表结束')
});

/* 输出:
水果: 苹果
水果: 香蕉
水果: 橙子
水果列表结束
*/

// 发出不同类型的数据
of(
  '字符串',
  123,
  true,
  {name: 'Alice'},
  [1, 2, 3],
  function hello() { return 'world'; }
).subscribe(val => console.log('收到的值:', val));

// 实际应用:模拟API返回
function mockApiCall() {
  return of({id: 1, name: '用户1'});
}

mockApiCall().subscribe(user => {
  console.log('用户数据:', user);
});

3. from 操作符详细用法

from 可以将多种数据类型转换为 Observable。

各种来源的转换

import { from } from "rxjs";

// 1. 从数组创建
from([10, 20, 30]).subscribe(num => console.log('数字:', num));

// 2. 从Promise创建
const promise = fetch('https://api.example.com/data')
  .then(response => response.json());

from(promise).subscribe(data => {
  console.log('API数据:', data);
});

// 3. 从字符串创建 (每个字符作为单独的值)
from('Hello').subscribe(char => console.log(char));
// 输出: H, e, l, l, o

// 4. 从Map或Set创建
const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 25);

from(myMap).subscribe(entry => {
  console.log('Map条目:', entry);
  // 输出: ['name', 'Alice'], ['age', 25]
});

// 5. 实际应用:批量处理数组
const userIds = [1, 2, 3, 4];

from(userIds).subscribe(id => {
  console.log('处理用户ID:', id);
  // 这里可以调用API获取每个用户的详细信息
});

4. forkJoin 操作符详细用法

forkJoin 用于并行执行多个 Observable,等待它们全部完成。

完整示例

import { forkJoin, of, from, throwError } from "rxjs";
import { delay, catchError } from "rxjs/operators";

// 模拟API函数
function getUser(id) {
  return of({ id, name: `用户${id}` }).pipe(delay(1000));
}

function getUserPosts(userId) {
  const posts = [
    { id: 1, title: '帖子1' },
    { id: 2, title: '帖子2' }
  ];
  return of(posts).pipe(delay(1500));
}

function getUserComments(userId) {
  return from(fetch(`https://api.example.com/users/${userId}/comments`));
}

// 1. 基本用法
forkJoin([
  getUser(1),
  getUserPosts(1),
  getUserComments(1).pipe(
    catchError(error => of(`获取评论失败: ${error.message}`))
  )
]).subscribe({
  next: ([user, posts, comments]) => {
    console.log('用户:', user);
    console.log('帖子:', posts);
    console.log('评论:', comments);
  },
  error: err => console.error('整体失败:', err),
  complete: () => console.log('所有请求完成')
});

// 2. 对象形式更清晰
forkJoin({
  user: getUser(1),
  posts: getUserPosts(1),
  comments: getUserComments(1).pipe(
    catchError(error => of([])) // 错误时返回空数组
  )
}).subscribe({
  next: result => {
    console.log('整合结果:', result);
    // 结构: { user: {...}, posts: [...], comments: [...] }
  }
});

// 3. 错误处理演示
forkJoin({
  success: of('成功'),
  failure: throwError(new Error('出错了'))
}).pipe(
  catchError(error => {
    console.log('捕获到错误:', error);
    return of({ success: null, failure: error.message });
  })
).subscribe(result => {
  console.log('最终结果:', result);
});

// 4. 实际应用:并行请求多个API
function loadDashboardData() {
  return forkJoin({
    user: getUser(1),
    notifications: from(fetch('/api/notifications')),
    settings: from(fetch('/api/settings'))
  });
}

loadDashboardData().subscribe(data => {
  console.log('仪表盘数据:', data);
  // 更新UI...
});

综合实战示例

import { forkJoin, from, of } from "rxjs";
import { map, mergeMap, catchError } from "rxjs/operators";

// 模拟API服务
class ApiService {
  static getUsers() {
    const users = [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ];
    return of(users).pipe(delay(500));
  }
  
  static getUserDetails(userId) {
    const details = {
      1: { age: 25, email: 'alice@example.com' },
      2: { age: 30, email: 'bob@example.com' }
    };
    return of(details[userId]).pipe(delay(300));
  }
  
  static getUserPosts(userId) {
    const posts = {
      1: [{ id: 101, title: 'Alice的第一篇帖子' }],
      2: [{ id: 201, title: 'Bob的帖子' }, { id: 202, title: 'Bob的另一篇帖子' }]
    };
    return of(posts[userId] || []).pipe(delay(700));
  }
}

// 1. 获取所有用户及其详细信息和帖子
ApiService.getUsers().pipe(
  mergeMap(users => {
    // 为每个用户创建请求数组
    const userRequests = users.map(user => 
      forkJoin({
        details: ApiService.getUserDetails(user.id),
        posts: ApiService.getUserPosts(user.id)
      }).pipe(
        map(data => ({ ...user, ...data }))
      )
    );
    
    // 并行执行所有用户请求
    return forkJoin(userRequests);
  })
).subscribe({
  next: completeUsers => {
    console.log('完整用户数据:', completeUsers);
    /* 输出:
    [
      {
        id: 1,
        name: 'Alice',
        details: { age: 25, email: 'alice@example.com' },
        posts: [{ id: 101, title: 'Alice的第一篇帖子' }]
      },
      {
        id: 2,
        name: 'Bob',
        details: { age: 30, email: 'bob@example.com' },
        posts: [{...}, {...}]
      }
    ]
    */
  },
  error: err => console.error('获取用户数据失败:', err)
});

// 2. 实际应用:表单提交后并行更新多个资源
function updateResources(userData, postsData, settingsData) {
  return forkJoin({
    user: from(fetch('/api/user', {
      method: 'PUT',
      body: JSON.stringify(userData)
    })),
    posts: from(fetch('/api/posts', {
      method: 'POST',
      body: JSON.stringify(postsData)
    })),
    settings: from(fetch('/api/settings', {
      method: 'PATCH',
      body: JSON.stringify(settingsData)
    }))
  }).pipe(
    map(responses => ({
      user: responses.user.json(),
      posts: responses.posts.json(),
      settings: responses.settings.json()
    }))
  );
}

// 使用示例
updateResources(
  { name: '新名字' },
  [{ title: '新帖子' }],
  { theme: 'dark' }
).subscribe({
  next: results => {
    console.log('所有资源更新成功:', results);
  },
  error: err => {
    console.error('更新失败:', err);
    // 显示错误提示
  }
});

这些示例展示了 RxJS 操作符在实际开发中的典型用法。关键点:

  1. Observable 是基础,代表数据流
  2. of 用于创建简单的同步流
  3. from 用于从各种数据源创建流
  4. forkJoin 用于并行执行多个 Observable 并合并结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2384603.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频监控管理平台EasyCVR结合AI分析技术构建高空抛物智能监控系统,筑牢社区安全防护网

高空抛物严重威胁居民生命安全与公共秩序,传统监管手段存在追责难、威慑弱等问题。本方案基于EasyCVR视频监控与AI视频分析技术(智能分析网关),构建高空抛物智能监控系统,实现24小时实时监测、智能识别与精准预警&…

2.2.1 05年T1复习

引言 从现在进去考研英语基础阶段的进阶,主要任务还是05-09年阅读真题的解题,在本阶段需要注意正确率。阅读最后目标:32-34分,也就是每年真题最多错四个。 做题步骤: 1. 预习:读题干并找关键词 做题&#…

Python-11(集合)

与字典类似,集合最大的特点就是唯一性。集合中所有的元素都应该是独一无二的,并且也是无序的。 创建集合 使用花括号 set {"python","Java"} print(type(set)) 使用集合推导式 set {s for s in "python"} print(set…

Opixs: Fluxim推出的全新显示仿真模拟软件

Opixs 是 Fluxim 最新研发的显示仿真模拟软件,旨在应对当今显示技术日益复杂的挑战。通过 Opixs,研究人员和工程师可以在制造前,设计并验证 新的像素架构,从而找出更功节能、色彩表现更优的布局方案。 Opixs 适用于学术研究和工业…

佰力博与您探讨PVDF薄膜极化特性及其影响因素

PVDF(聚偏氟乙烯)薄膜的极化是其压电性能形成的关键步骤,通过极化处理可以显著提高其压电系数和储能能力。极化过程涉及多种方法和条件,以下从不同角度详细说明PVDF薄膜的极化特性及其影响因素。 1、极化方法 热极化:…

自动获取ip地址安全吗?如何自动获取ip地址

在数字化网络环境中,IP地址的获取方式直接影响设备连接的便捷性与安全性。自动获取IP地址(通过DHCP协议)虽简化了配置流程,但其安全性常引发用户疑虑。那么,自动获取IP地址安全吗?如何自动获取IP地址&#…

STM32:深度解析RS-485总线与SP3485芯片

32个设备 知识点1【RS-485的简介】 RS-485是一种物理层差分总线标准,在串口的基础上演变而来; 两者虽然不在同一层次上直接对等,但在实际系统中,往往使用RS-485驱动差分总线,将USART转换为适合长距离、多点通信的物…

亚马逊搜索代理: 终极指南

文章目录 前言一、为什么需要代理来搜索亚马逊二、如何选择正确的代理三、搜索亚马逊的最佳代理类型四、为亚马逊搜索设置代理五、常见挑战及克服方法六、亚马逊搜索的替代方法总结 前言 在没有代理的情况下搜索亚马逊会导致 IP 禁止、验证码和速度限制,从而使数据…

C++笔记-封装红黑树实现set和map

1.源码及框架分析 上面就是在stl库中set和map的部分源代码。 通过上图对框架的分析,我们可以看到源码中rb_tree⽤了⼀个巧妙的泛型思想实现,rb_tree是实 现key的搜索场景,还是key/value的搜索场景不是直接写死的,⽽是由第⼆个模板…

留给王小川的时间不多了

王小川,这位头顶“天才少年”光环的清华学霸、搜狗输入法创始人、中国互联网初代技术偶像,正迎来人生中最难啃的硬骨头。 他在2023年创立的百川智能,被称为“大模型六小虎”之一。今年4月,王小川在全员信中罕见地反思过去两年工作…

国产频谱仪性能如何?矢量信号分析仪到底怎么样?

矢量信号分析仪是一种高性能的电子测量设备,具备频谱分析、矢量信号分析、实时频谱分析、脉冲信号分析、噪声系数测量、相位噪声测量等多种功能。它能够对各类复杂信号进行精确的频谱特性分析、调制质量评估、信号完整性检测以及干扰源定位等操作。广泛应用于通信、…

熔断器(Hystrix,Resilience4j)

熔断器 核心原理​ 熔断器通过监控服务调用失败率,在达到阈值时自动切断请求,进入熔断状态(类似电路保险丝)。其核心流程为: 关闭状态(Closed)​​:正常处理请求,统计失…

C++23 容器从其他兼容范围的可构造性与可赋值性 (P1206R7)

文章目录 背景与动机提案内容与实现细节提案 P1206R7实现细节编译器支持 对开发者的影响提高灵活性简化代码向后兼容性 总结 C23标准引入了对容器构造和赋值的新特性,这些特性使得容器能够更灵活地从其他兼容范围初始化,并支持从范围赋值。这些改进由提案…

多通道振弦式数据采集仪MCU安装指南

设备介绍 数据采集仪 MCU集传统数据采集器与5G/4G,LoRa/RS485两种通信功能与一体的智能数据采集仪。该产品提供振弦、RS-485等的物理接口,能自动采集并存储多种自然资源、建筑、桥梁、城市管廊、大坝、隧道、水利、气象传感器的实时数据,利用现场采集的数…

SOC-ESP32S3部分:9-GPIO输入按键状态读取

飞书文档https://x509p6c8to.feishu.cn/wiki/L6IGwHKV6ikQ08kqwAwcAvhznBc 前面我们学习了GPIO的输出,GPIO输入部分其实也是一样的,这里我们使用按键作为GPIO输入例程讲解,分三步走。 查看板卡原理图,确定使用的是哪个GPIO查看G…

Ubuntu20.04的安装(VMware)

1.Ubuntu20.04.iso文件下载 下载网址:ubuntu-releases-20.04安装包下载_开源镜像站-阿里云 2.创建虚拟环境 2.1打开VMware与创建新虚拟机 点击创建新虚拟机 如果没下好可以点击稍后安装操作系统 选择linux版本选择Ubuntu 64位然后点击下一步。 注意这里需要选择一…

【论文阅读】LLaVA-OneVision: Easy Visual Task Transfer

LLaVA-OneVision: Easy Visual Task Transfer 原文摘要 研究背景与目标 开发动机: 基于LLaVA-NeXT博客系列对数据、模型和视觉表征的探索,团队整合经验开发了开源大型多模态模型 LLaVA-OneVision。 核心目标: 突破现有开源LMM的局限&#xf…

Spring Boot 项目多数据源配置【dynamic datasource】

前言: 随着互联网的发展,数据库的读写分离、数据迁移、多系统数据访问等多数据源的需求越来越多,我们在日常项目开发中,也不可避免的为了解决这个问题,本篇来分享一下在 Spring Boot 项目中使用多数据源访问不通的数据…

JAVA查漏补缺(2)

AJAX 什么是Ajax Ajax(Asynchronous Javascript And XML),即是异步的JavaScript和XML,Ajax其实就是浏览器与服务器之间的一种异步通信方式 异步的JavaScript 它可以异步地向服务器发送请求,在等待响应的过程中&…

【Web前端】JavaScript入门与基础(二)

Javascript对象 什么是对象?对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型。简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。 var…