RxJs 中的多播 — multicast、share、publish 之间的区别

阅读时长 10 分钟读完

前言

在 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。

上面的例子中,我们把 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 的两种不同的写法。但是实际上,它们之间还是存在一些细微的差别的。

  1. ConnectableObservable 的默认连接行为不同

在一个未连接的 ConnectableObservable 上调用 subscribe 方法时,publish 会自动调用 connect 方法,数据开始发射。但是 multicast 不会自动连接,我们需要手动调用 connect 方法才会让数据开始发射。

-- -------------------- ---- -------
------ - -------- - ---- -------
------ - -------- --------- - ---- -----------------

----- ------ - ---------------
----- ----------- - ------------------------- ------------
----- --------- - -----------------------

-- ----------- ------
------------------------- -- --------------------------- ------

-- --------- ------------
----------------------- -- ------------------------- ------
  1. 实现方式不同

publish 和 share 都是基于 multicast 实现的。但是 share 是一个直接可以使用的操作符,而 publish 需要手动创建 ConnectableObservable。

-- -------------------- ---- -------
------ - -------- - ---- -------
------ - ------ -------- -------- - ---- -----------------

----- ------ - ---------------
----- ------ - ---------------------
----- --------- - ---------------------- ------------

-------------------- -- ---------------------- ------
----------------------- -- ------------------------- ------

在上面的代码中,我们使用了 refCount 操作符,这样就可以借助 share 的方便性实现了 publish 的效果。

  1. 订阅行为不同

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

纠错
反馈