前言
在 RxJs 中进行数据处理时,多播(multicast)是一项非常重要的技术。多播的主要作用是可以让多个订阅者共享来自 Observable 的数据。在 RxJs 中,提供了三种多播的方式:multicast、share、publish。虽然它们都可以实现多播,但是在具体使用时,它们之间的区别确实非常重要。
本篇文章将详细介绍三种多播的功能、使用方式和区别,并且提供一些示例代码供大家参考。
multicast
multicast 是多播中最底层的一个 API。它需要和 Subject(也可以是自定义的 Subject 的子类)一起使用。简单来说,multicast 就是先创建一个 Subject,然后把一个 Observable 链接到它上面,最后返回一个新的 Observable。
-- -------------------- ---- ------- ------ - --------- ------- - ---- ------- ------ - --------- - ---- ----------------- ----- ------ - --------------- ----- ------- - --- ---------- ----- ----------- - -------------------------------- ------------------------- -- ----------------------- ---- ------ ------------------------- -- ----------------------- ---- ------ ----------------------
上面的例子中,我们使用 interval 创建了一个每 1000 毫秒发射一次数据的 Observable。然后我们创建了一个新的 Subject,并使用 multicast 把 interval 和 Subject 连接起来,最后返回一个新的 Observable。
在执行 subscribe 操作之前,我们要先调用 connect 方法,这样数据才会开始发射。
这个例子中,我们创建了两个订阅者,它们都可以收到 interval 发射的数据。
multicast 不会自动连接 Observable。我们必须手动调用 connect 方法,才会让数据开始发射。
share
share 是基于 multicast 封装的一个操作符,它可以自动处理 Observable 的连接状态。share 接收一个参数,它可以是一个 Subject,也可以是 Subject 的工厂函数。如果没有提供参数,share 就会创建一个新的 Subject。
import { interval } from 'rxjs'; import { share } from 'rxjs/operators'; const source = interval(1000).pipe(share()); source.subscribe(val => console.log('Subscriber 1:', val)); source.subscribe(val => console.log('Subscriber 2:', val));
上面的例子中,我们把 interval 和 share 结合起来,创建了一个新的 Observable。我们没有手动调用 connect 方法,share 会自动处理连接状态,所以数据会自动开始发射。
publish
publish 与 multicast 类似,它也需要一个 Subject。不同的是,publish 返回的是一个 ConnectableObservable。和 multicast 一样,我们也需要手动调用 connect 方法才会让数据开始发射。
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - ------- - ---- ----------------- ----- ------ - --------------- ----- --------- - ----------------------- ----------------------- -- ----------------------- ---- ------ ----------------------- -- ----------------------- ---- ------ --------------------
在上面的例子中,我们创建了一个新的 Observable,使用 publish 和 interval 连接起来,并且返回一个 ConnectableObservable。我们手动调用 connect 方法,让数据开始发射。
和 multicast 不同的是,publish 返回的是 ConnectableObservable,所以我们不需要手动调用 connect 方法。ConnectableObservable 会自动在第一个订阅者订阅时开始发射数据。
区别
在平时的开发中,我们可能会把 multicast 和 publish 当做是 share 的两种不同的写法。但是实际上,它们之间还是存在一些细微的差别的。
- ConnectableObservable 的默认连接行为不同
在一个未连接的 ConnectableObservable 上调用 subscribe 方法时,publish 会自动调用 connect 方法,数据开始发射。但是 multicast 不会自动连接,我们需要手动调用 connect 方法才会让数据开始发射。
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - -------- --------- - ---- ----------------- ----- ------ - --------------- ----- ----------- - ------------------------- ------------ ----- --------- - ----------------------- -- ----------- ------ ------------------------- -- --------------------------- ------ -- --------- ------------ ----------------------- -- ------------------------- ------
- 实现方式不同
publish 和 share 都是基于 multicast 实现的。但是 share 是一个直接可以使用的操作符,而 publish 需要手动创建 ConnectableObservable。
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - ------ -------- -------- - ---- ----------------- ----- ------ - --------------- ----- ------ - --------------------- ----- --------- - ---------------------- ------------ -------------------- -- ---------------------- ------ ----------------------- -- ------------------------- ------
在上面的代码中,我们使用了 refCount 操作符,这样就可以借助 share 的方便性实现了 publish 的效果。
- 订阅行为不同
publish 和 multicast 都是通过一个 Subject 来实现多播的。但是在使用时,我们可能会遇到一些订阅行为的问题。
对于 multicast,我们可以手动创建一个 Subject,并显式地调用 connect 方法来控制订阅行为。在订阅时,我们还需要使用里面的 asObservable 方法,因为我们不想订阅者可以自己调用 next 方法。
-- -------------------- ---- ------- ------ - --------- ------- - ---- ------- ------ - --------- - ---- ----------------- ----- ------ - --------------- ----- ------- - --- ---------- ----- ----------- - -------------------------------- ----- ----------- - ------------------------- -- ----------------------- ---- ------ ----- -------- - ---------------------- ----- ----------- - ---------------------- -- ----------------------- ---- ------ ----------------------
而在 publish 中,我们也需要手动创建一个 Subject,但是我们不需要手动调用 connect 方法。这是因为 publish 返回的是 ConnectableObservable。但是在订阅时,我们需要注意一下,因为 ConnectableObservable 默认是共享订阅者,对于新的订阅者,会重复收到一遍已经发射过的数据。
-- -------------------- ---- ------- ------ - --------- ------- - ---- ------- ------ - ------- - ---- ----------------- ----- ------ - --------------- ----- ------- - --- ---------- ----- --------- - ----------------------- ----- ----------- - ----------------------- -- ----------------------- ---- ------ ----- ----------- - ----------------------- -- ----------------------- ---- ------ --------------------
在上面的例子中,我们创建了两个订阅者,虽然它们都会收到 interval 发射的数据,但是它们会看到两次相同的数据。这是因为 ConnectableObservable 会缓存已经发射过的数据。
为了避免新的订阅者收到重复数据,我们可以使用 refCount 操作符,这样就可以在最后一个订阅者取消订阅时,让 ConnectableObservable 自动停止数据发射。
-- -------------------- ---- ------- ------ - -------- - ---- ------- ------ - -------- -------- - ---- ----------------- ----- ------ - --------------- ----- --------- - ---------------------- ------------ ----- ----------- - ----------------------- -- ----------------------- ---- ------ ----- ----------- - ----------------------- -- ----------------------- ---- ------ -- - -------------- --------- ------------- -- - ------------------------ ---------- ---- -------------------------- -- ------
总结
在使用 RxJs 时,多播技术是一个非常实用且重要的技术。通过本文我们深入学习了 RxJs 中 multicast、share、publish 之间的区别,并给出了详细的示例代码。在实际开发中,我们需要注意以上差异,选择合适的方法进行多播,以达到更好的效果。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/649eac1e48841e9894b37aca