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,获取服务器返回的结果。当用户选择一个结果时,我们可以触发一个事件,让父组件处理。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d9c9f5a941bf7134186357