使用这 5 个 RxJS 运算符释放 Angular 的全部潜力

5 个你不知道你需要的 RxJS 操作符(直到现在!)

响应式编程改变了我们在 JavaScript 中处理异步数据的方式。RxJS(JavaScript 的响应式扩展)是一个功能强大的库,它使处理数据流变得轻而易举。虽然“map”、“filter”和“mergeMap”等运算符很常用,但 RxJS 有许多隐藏的精华,可以简化复杂的逻辑。本指南介绍了五个鲜为人知的 RxJS 运算符,解释了它们的用例以及如何逐步实现它们。

什么是 RxJS 运算符?

RxJS 运算符是允许您以各种方式转换、过滤或组合可观察对象的函数。它们使处理异步流更具声明性和直观性。通过链接运算符,您可以构建强大的响应式工作流。

为什么要使用鲜为人知的运算符?

RxJS 中的一些运算符可以解决非常具体的问题或提高代码的可读性和性能。学习这些隐藏的精华可以让你的代码更高效、更优雅。

1.partition:分割流

什么是分区?

`partition` 运算符用于根据谓词将单个可观察对象拆分为两个可观察对象。一个可观察对象发出满足谓词的值,另一个可观察对象发出其余值。

何时使用它?

当您需要在单独的流中处理不同类型的数据时,请使用“分区”,例如过滤错误或分离偶数和奇数。

示例:拆分偶数和奇数

步骤 1:导入所需的 RxJS 操作符

import { from } from 'rxjs';
import { partition } from 'rxjs/operators';

第 2 步:创建可观察对象

const numbers$ = from([1, 2, 3, 4, 5, 6, 7, 8, 9]);

步骤 3:使用分区

const [even$, odd$] = partition(numbers$, (num) => num % 2 === 0);

步骤 4:订阅两个流

even$.subscribe((num) => console.log(`Even: ${num}`));
odd$.subscribe((num) => console.log(`Odd: ${num}`));

输出

Even: 2  
Even: 4  
Even: 6  
Even: 8  
Odd: 1  
Odd: 3  
Odd: 5  
Odd: 7  
Odd: 9

重点

“分区”简化了原本需要多个“过滤”运算符的逻辑。

2.combineLatestWith:合并最新值

什么是 CombineLatestWith?

该运算符将来自多个可观察对象的最新值组合成一个可观察对象。

何时使用它?

当您需要同时对多个流中的变化做出反应时,请使用“combineLatestWith”,例如将用户输入与实时数据相结合。

示例:结合用户输入和 API 数据

步骤 1:导入所需的 RxJS 操作符

import { fromEvent, of } from 'rxjs';
import { combineLatestWith } from 'rxjs/operators';

第 2 步:创建可观察对象

const input$ = fromEvent(document.getElementById('input'), 'input');
const apiData$ = of({ name: 'John Doe', age: 30 });

步骤 3:合并流

input$
  .pipe(combineLatestWith(apiData$))
  .subscribe(([event, data]) => {
    console.log(`Input: ${event.target.value}, API Data: ${JSON.stringify(data)}`);
  });

输出

Input: Hello, API Data: {"name":"John Doe","age":30}

重点

`combineLatestWith` 非常适合实时同步多个流。

3. 审计:精准节流

什么是审计?

“审计”运算符在指定的持续时间后从源可观察对象发出最新值。

何时使用它?

当您想要控制排放时,请使用“审计”,例如在拖放事件或滚动期间。

示例:发出滚动事件

步骤 1:导入所需的 RxJS 操作符

import { fromEvent, interval } from 'rxjs';
import { audit } from 'rxjs/operators';

第 2 步:创建滚动可观察对象

const scroll$ = fromEvent(window, 'scroll');

步骤3:申请审核

scroll$
  .pipe(audit(() => interval(1000)))
  .subscribe(() => console.log('Scrolled!'));

输出

Scrolled!  
Scrolled!

重点

`audit` 确保精确节流而不会丢失最新值。

4. 扩展:递归可观察对象

什么是 expand?

“expand”运算符以递归方式将每个发射的值投射到新的可观察对象中。

何时使用它?

对于递归 API 调用或树遍历等场景,请使用“expand”。

示例:获取分页数据

步骤 1:导入所需的 RxJS 操作符

import { of } from 'rxjs';
import { expand, take } from 'rxjs/operators';

步骤 2:模拟 API 调用

const fetchPage = (page) => of(`Page ${page}`);

步骤 3:使用 expand

fetchPage(1)
  .pipe(
    expand((page) => (page < 5 ? fetchPage(page + 1) : of())),
    take(5)
  )
  .subscribe((data) => console.log(data));

输出

Page 1  
Page 2  
Page 3  
Page 4  
Page 5

重点

`expand` 非常适合优雅地处理递归操作。

5. groupBy:组织流

什么是 groupBy?

`groupBy` 操作符将一个可观察对象拆分为多个可观察对象,并按指定的键分组。

何时使用它?

当您需要动态地对数据进行分类时,请使用“groupBy”,例如按严重性组织日志。

示例:分组日志

步骤 1:导入所需的 RxJS 操作符

import { from } from 'rxjs';
import { groupBy, mergeMap, toArray } from 'rxjs/operators';

第 2 步:创建日志可观察对象

const logs$ = from([
  { level: 'info', message: 'App started' },
  { level: 'error', message: 'Unhandled exception' },
  { level: 'info', message: 'User logged in' },
  { level: 'warn', message: 'Deprecated API' },
]);

步骤 3:使用 groupBy

logs$
  .pipe(
    groupBy((log) => log.level),
    mergeMap((group) => group.pipe(toArray()))
  )
  .subscribe((groupedLogs) => console.log(groupedLogs));

输出

[{ level: 'info', message: 'App started' }, { level: 'info', message: 'User logged in' }]  
[{ level: 'error', message: 'Unhandled exception' }]  
[{ level: 'warn', message: 'Deprecated API' }]

重点

`groupBy` 简化了按类别动态组织数据。

常见问题解答

最常见的 RxJS 操作符有哪些?

诸如“map”、“filter”和“mergeMap”之类的操作符被广泛用于转换和过滤数据流。

我该如何选择合适的运营商?

根据数据流需求选择操作符,使用 `partition` 进行拆分,使用 `combineLatestWith` 进行同步,使用 `groupBy` 进行分类。

这些运算符可以组合吗?

是的,您可以链接这些操作符来构建复杂的工作流程,例如将“partition”与“expand”结合起来以实现高级逻辑。

学习这五个 RxJS 运算符将帮助您编写更简洁、更高效的响应式代码。开始尝试这些示例,观察您的 Angular 应用程序变得更加动态和强大!