漫谈RxJS之实战篇

2,110 阅读3分钟

这是我参与 8 月更文挑战的第 29 天,活动详情查看: 8月更文挑战

上篇文章我们谈到了一些基础概念,本篇文章我们结合实际案例来继续探索RxJS。

带来了什么新问题?

不得不说,Reactive Extensions(Rx)是一种非常棒的编码模式,不过我们得结合实际的业务场景做具体分析。

  1. 团队内的成员是否具备高度抽象思维,因为这是一种函数式、响应式编程范式,团队成员是否可以快速学习进入开发?
  2. RxJS最擅长处理的是异步事件,那么我们的业务场景是否真的有这么复杂吗?
  3. RxJS的代码是高度抽象的,抽象的代码是不如命令式代码易读,这点无可厚非,那么我们该如何组织我们的业务代码?

函数式编程范式

这里顺带提一下函数式编程范式,首先,这是一种有约束的编程范式:

  1. 声明式(Declarative)

声明式,与之对应的是命令式,我们可以看下代码有何不同:

const arr = [1, 2, 3, 4, 5]
// 命令式
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i])
}

// 声明式
arr.map((item) => {
    console.log(item)
})

我们不难发现,使用声明式,代码简洁很多,看不到for了,也没有了额外的变量声明。

  1. 纯函数(Pure Function)

函数的调用不会有额外的副作用(IO操作、DOM操作、网络请求等),每次的输入都有唯一确认的输出。

  1. 数据不可变性(Immutability)

不改变源数据,举个例子:

const arr = [1, 2, 3, 4, 5]
// 改变了源数据
arr.push(6)

// 添加了新元素,但并没有改变原始数据,符合数据不可变性原则
function push2(source, item) {
    return [...source, item]
}

结合实际业务场景

这也是我最近做的例子,个人觉得结合RxJS会比较合适,就是IM聊天会话页。

我们先来梳理一下逻辑:

事件:

  1. 通过HTTP GET拉取历史会话列表;
  2. 通过websocket协议实时接收消息;
  3. 输入事件;
  4. 发送内容事件;
  5. 点击内容事件(如图片预览、视频播放、语音播放等);

我们结合下UI交互,再组织下逻辑层,不难发现:

  1. 对于【聊天内容显示区域】,很明显是订阅者,订阅者的特点是什么?上文已提过:订阅者只负责接收到通知后完成自身的业务逻辑,而并不关心消息的来源

  2. 发布者有哪些?

    • 通过websocket推送的消息(异步事件)
    • 通过HTTP GET拉取的消息(异步事件)
    • 用户点击发送的消息(同步事件)

一个订阅者支持订阅多个事件流吗?RxJS当然支持,我们可以通过合并事件流、转化事件流等手段,来达到我们的目的。

这里代码就不贴了,感兴趣的同学可以按上述思路实践一下。

小结

本文还有很多RxJS的概念没有介绍到,比如:

  • Hot Observable和Cold Observable用于解决存在多个订阅者,有人会迟到的问题
  • 经典的弹珠图表示法,让我们可以清晰的看到事件的流向
  • 多播,用于处理一个事件流存在多个订阅者的问题
  • 异常处理,上游的数据出错了如何处理
  • ...

如果大家有感兴趣的点,也欢迎随时讨论。