为了理清楚复杂的业务数据,我们通常会在组件之上,在视图渲染之下建立数据中间层。
Promise, Generator , Reactive
我们用 react ,用 redux 做数据状态管理。数据有同步有异步,前端大量的工作在于处理异步数据。通常有几种方式:
再总结下实际数据处理中存在的问题:
统一同步和异步 Promise 处理同步和异步 (用resolve 把同步转成异步)
Reactive 处理同步和异步
Reactive 的优点在于 subscribe
可以响应多次
Promise 的有点在于编写简单
统一获取和订阅的逻辑 对于某一个数据的更新,其实我们不需要知道它是直接获取的,还是被动推送而更新的,我们只需要知道它变了。所以Reactive 响应多次的优点就有用武之地了。
同样做对比: Promise 实现获取的订阅:
Reactive 实现获取的订阅:
Promise 需要区分 获取 和 订阅 Reactive 则直接描述了一个统一的业务过程:数据有变
数据组合
组合有多重情况
Reactive 制定一套组合规则,并不需要考虑数据是获取的or 推送的。
按需获取 使用 Promise 、或者接受变动进而主动更新状态的做法,往深层次想都不是按需操作。因为更新的状态可能并不完全需要显示,很可能会有更新的状态并不需要显示(或者我们很难控制没有副作用的更新)。
比如 数据实体 a 变了,我们需要把所有引用到 a 的变量都更新一遍,比如因此更新了 数据实体 c,但数据实体 c 此时是不需要显示的,这样就是副作用。
但 Reactive ,是从使用者的角度看问题,只会对订阅的数据更新。 如果数据实体 a 变了,引用了 a 的数据实体 c, 此时并没有被订阅,他并不会产生更新,不需要走可能很复杂的一套组合规则。
Promise 、Generator 和 Async Await 关注点是流程控制,像写同步一样的写异步目的之一就是为了让整个异步流程可控方便追踪。 事件和回调关注点是消息通知,比如基于事件和回调的订阅接收模型,前端有大量的消息需要逆异步流程传递(随意传递)。
随之而来的问题就是:
所以,对大规模复杂应用,用 Promise 、Generator 和 Async Await 们控制流程比事件回调更合适,但制定更多的流程规则会带来代码『人工复杂度』(重复劳动啊)上的问题。
比如我们 redux-thunk 处理异步,越写到后面越难受,一个简单的业务逻辑很可能会需要写出好几套 reducer 和 action。redux-thunk 就是基于 promise 的。
相应的,redux-saga 是基于 Generator 的,蚂蚁为了简化流程制定,在 redux-saga 基础上搞了 dva。
另一个思路是 Reactive,很多人说 Reactive 是综合了流程控制和消息通知。我理解 Reactive 的重点是两个,响应和需求。
用所谓的响应式 Reactive 编程,我们不关注什么流程、什么消息,我们只需要关注针对什么刺激需要出哪些响应结果。Reactive 的库 rxjs 提供的各种流程操作并不是重点,重点是为了让人不要关心过程,而是关心刺激和响应的结果。这是一种完全不同的思路。
相应的,redux-observable 是基于 Reactive(rxjs) 的。
用 Reactive 的理念管理数据就会变成这样:
完全,直接按需获取。。不需要考虑数据变了要怎样,状态变了要怎样,怎么通知。理论上来说,这个理念似乎是最没有附加冗余的异步逻辑抽象。
但实际用起来,也还是会有问题的:
所以选哪一套方案,是个难有结论的问题。