【发布时间】:2021-09-26 15:52:15
【问题描述】:
请注意:尽管我在示例中使用 Swift-lang,但我鼓励您尝试帮助我,即使您了解 RxJava 和 rxjs 或任何其他 Rx 实现。
问题:我有一个命令式编写的状态机。我想使用 Rx 进行响应式重写,但我正在努力想出正确的方法。
当前的命令式系统如下所示:
var state: State
var metaState: MetaState
func updateMetaStateIfNeeded() {
if Bool.random() {
metaState = MetaState()
}
}
func tick() -> State {
updateMetaStateIfNeeded()
let newState = State(currentState: state, metaState: metaState)
self.state = newState
return newState
}
到目前为止我想出了什么:
let tick = PublishSubject<Void>()
let metaState = BehaviorSubject<MetaState>()
let state = BehaviorSubject<State>()
let tickAfterMetaStateUpdate = PublishSubject<Void>()
tick -> withLatestFrom metaState -> map to new metaState if update needed or the old one -> put result into metaState AND tickWithUpdatedMetaState
tickAfterMetaStateUpdate -> withLatestFrom state AND metaState -> map State(currentState: state, metaState: metaState) -> put result into state
(The users of this API subscribe to state subject, which will be updated every tick)
我对我提出的这个结果不满意。我想知道是否可以使用scan 或reduce 重写它,这样就没有使用 Subjects 并且它是一个普通的 Observable。
@Daniel T. 回答后更新:
哇,这正是正确的解决方案!我已经准备好了分析:
- 有2个状态机,一个用于
metaState更新,一个用于state更新 - 他们每个人都有自己的开始状态,我们不需要指定
-
metaState的输入字母是Void,只是一个勾号。对于state,它是第一个状态机的metaState输出
所以有了这个理解,我用 2 次扫描重写了系统:
let state = tick
.scan(MetaState()) { currentMetaState, void in
if Bool.random() {
return MetaState()
}
return currentMetaState
}
.scan(State()) { currentState, currentMetaState in
State(currentState: state, metaState: metaState)
}
WINRAR! Mind_blast.jpg!实际上,事后看来,这似乎很明显...... :) 谢谢,谢谢,谢谢!
【问题讨论】:
-
如果您愿意,我很高兴在RxSwift slack channel 上进一步讨论这个问题。
标签: rxjs rx-java reactive-programming rx-swift frp