RxJS 是一种基于事件流和数据流的编程模式,它可以让我们更容易的处理异步数据,比如网络请求、用户输入、定时器等等。在 Angular6 中,RxJS 是一个非常重要的工具,几乎每个 Angular 应用都需要用到它。本文将介绍完整的 RxJS 学习笔记,包括基础概念、操作符、实践案例等等。
基础概念
Observable
Observable 是 RxJS 中最重要的概念之一,它代表一个可以被订阅的事件流。我们可以通过 Observable.create() 或 new Observable() 来创建一个 Observable,如下所示:
import { Observable } from 'rxjs';
const observable = new Observable(subscriber => {
subscriber.next(1);
subscriber.next(2);
subscriber.next(3);
subscriber.complete();
});在上面的代码中,我们创建了一个 Observable,它会依次发出数字 1、2、3,然后完成。我们可以通过 subscribe() 方法来订阅这个 Observable,如下所示:
observable.subscribe({
next: value => console.log(value),
complete: () => console.log('complete')
});在上面的代码中,我们订阅了这个 Observable,当它发出事件时,我们会依次输出数字 1、2、3,最后输出 'complete'。
Operator
Operator 是 RxJS 中用来操作 Observable 的方法,它可以对 Observable 发出的每个事件进行处理,比如过滤、映射、合并等等。我们可以通过 pipe() 方法来使用 Operator,如下所示:
-- -------------------- ---- ------- ------ - -- - ---- ------- ------ - ------- --- - ---- ----------------- ----- ------ - ----- -- -- -- --- ----- ------ - ------------ ------------ -- ----- - - --- --- --------- -- ----- - ------ -- ---------------------- -- --------------------
在上面的代码中,我们创建了一个 Observable,它会依次发出数字 1、2、3、4、5。然后我们使用 filter() 操作符过滤出偶数,再使用 map() 操作符将偶数平方。最后输出数字 4、16。
Subject
Subject 是 RxJS 中另一个重要的概念,它既是 Observable,又是 Observer。我们可以通过 new Subject() 来创建一个 Subject,如下所示:
-- -------------------- ---- ------- ------ - ------- - ---- ------- ----- ------- - --- ---------- ------------------- ----- ----- -- ----------------------- ---- ------ --- ---------------- ------------------- ----- ----- -- ----------------------- ---- ------ --- ----------------
在上面的代码中,我们创建了一个 Subject,它可以被多个订阅者订阅。当我们调用 next() 方法时,所有订阅者都会收到这个事件。在上面的代码中,首先订阅者 1 收到数字 1,然后订阅者 2 也收到数字 1。接着订阅者 1 和订阅者 2 都收到数字 2。
常用操作符
map
map() 操作符用于将 Observable 中的每个事件都映射成新的事件。它的参数是一个函数,这个函数接收 Observable 发出的事件作为参数,返回一个新的事件。比如下面的例子:
-- -------------------- ---- ------- ------ - ---- - ---- ------- ------ - --- - ---- ----------------- ----- ------ - -------- -- -- -- ---- ----- ------ - ------------ --------- -- ----- - ------ -- ---------------------- -- --------------------
在上面的代码中,我们创建了一个 Observable,它会依次发出数字 1、2、3、4、5。然后我们使用 map() 操作符将每个数字平方。最后输出数字 1、4、9、16、25。
filter
filter() 操作符用于过滤 Observable 中的事件。它的参数是一个函数,这个函数接收 Observable 发出的事件作为参数,返回一个布尔值,表示是否保留这个事件。比如下面的例子:
-- -------------------- ---- ------- ------ - ---- - ---- ------- ------ - ------ - ---- ----------------- ----- ------ - -------- -- -- -- ---- ----- ------ - ------------ ------------ -- ----- - - --- -- -- ---------------------- -- --------------------
在上面的代码中,我们创建了一个 Observable,它会依次发出数字 1、2、3、4、5。然后我们使用 filter() 操作符过滤出偶数。最后输出数字 2、4。
take
take() 操作符用于从 Observable 中取出指定数量的事件。它的参数是一个数字,表示要取出的事件数量。比如下面的例子:
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - ---- - ---- ----------------- ----- ------ - --------------- ----- ------ - ------------ ------- -- ---------------------- -- --------------------
在上面的代码中,我们创建了一个 Observable,它会每隔 1 秒发出一个数字。然后我们使用 take() 操作符取出前 5 个数字。最后输出数字 0、1、2、3、4。
merge
merge() 操作符用于将多个 Observable 合并成一个 Observable。它的参数是多个 Observable,可以是数组或可变参数。比如下面的例子:
import { interval, merge } from 'rxjs';
const source1 = interval(1000);
const source2 = interval(2000);
const result = merge(source1, source2);
result.subscribe(value => console.log(value));在上面的代码中,我们创建了两个 Observable,它们分别每隔 1 秒和 2 秒发出一个数字。然后我们使用 merge() 操作符将它们合并成一个 Observable。最后输出数字 0、0、1、1、2、2、...。
combineLatest
combineLatest() 操作符用于将多个 Observable 中最新的事件合并成一个事件。它的参数是多个 Observable,可以是数组或可变参数。比如下面的例子:
import { interval, combineLatest } from 'rxjs';
const source1 = interval(1000);
const source2 = interval(2000);
const result = combineLatest([source1, source2]);
result.subscribe(value => console.log(value));在上面的代码中,我们创建了两个 Observable,它们分别每隔 1 秒和 2 秒发出一个数字。然后我们使用 combineLatest() 操作符将它们合并成一个 Observable。最后输出数组 [0, 0]、[1, 0]、[1, 1]、[2, 1]、[2, 2]、...。
实践案例
聊天室
下面是一个简单的聊天室应用,它使用了 Angular6 和 RxJS。用户可以输入用户名和消息,然后发送消息到服务器,服务器会广播这条消息给所有用户。每个用户都可以看到所有其他用户发送的消息。
-- -------------------- ---- -------
------ - --------- - ---- ----------------
------ - ---------------- - ---- -----------------
------------
--------- ----------------
--------- -
---- ----------- ------- -- ---------------------------
------ ---------------------- -----------------------
------ --------------------- ----------------------
------- ------------------------------
-
--
------ ----- ----------------- -
------- ------- ----------------------
------- --------- -------- - ---
------ --------- -------
------ -------- -------
------------- -
----------- - --- ----------------------------------------
----------------------------- -- -----------------------------
-
------ ------ -
----------------------------------- ------------------
------------ - ---
-
-在上面的代码中,我们使用了 WebSocketSubject 来创建一个 WebSocket 连接,然后订阅这个连接的消息。当用户点击发送按钮时,我们使用 next() 方法发送一条消息到服务器。
自动完成
下面是一个简单的自动完成组件,它使用了 Angular6 和 RxJS。用户可以输入关键字,然后从服务器获取匹配的结果,最后显示在下拉菜单中。当用户选择一个结果时,会触发一个事件。
-- -------------------- ---- -------
------ - --------- - ---- ----------------
------ - ----------- - ---- -----------------
------ - ------------- --------------------- --------- - ---- -----------------
------ - ---------- - ---- -----------------------
------------
--------- --------------------
--------- -
------ ------------------------
----
--- ----------- ------ -- -------- ----------------------------------------
-----
-
--
------ ----- --------------------- -
------- --- - -------------------------------
------ ------- - --- --------------
------ -------- -------- - ---
------------------- ----- ----------- -
-------------------------------
------------------
-----------------------
----------------- -- ----------------------------------------------------
------------------- -- ------------ - ---------
-
------ -------------- ------- -
-- ---- -----
-
-在上面的代码中,我们使用了 FormControl 来监听输入框的变化,然后使用 RxJS 操作符来处理输入事件。当用户输入一个关键字时,我们使用 debounceTime() 操作符来延迟发送请求,避免频繁请求。然后使用 distinctUntilChanged() 操作符来过滤掉重复的关键字。最后使用 switchMap() 操作符来将关键字转换成一个 Observable,然后订阅这个 Observable,获取服务器返回的结果。当用户选择一个结果时,我们可以触发一个事件,让父组件处理。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/67d9c9f5a941bf7134186357