@@ -14,28 +14,37 @@ import RxCocoa
14
14
/// Internally, Reducers come from registered Mutator defines a Reducer.
15
15
public final class Store < State: Equatable > {
16
16
17
- /// A Middleware acts like a valve in which a dispatched Action passes through.
18
- /// It cannot mutate the State. Middlewares can be used for logging purposes for instance
19
- public typealias Middleware = ( _ state: State , _ action: Action ) -> Void
17
+ /// Reducer correspond to the apply func of a Mutator
20
18
private typealias Reducer = ( State , Action ) -> State
21
19
22
- private var state : State
20
+ private let stateSubject : BehaviorRelay < State >
23
21
private var neededReducersPerSubState = [ String: Int] ( )
24
22
private var reducers = ContiguousArray < Reducer > ( )
25
- private var middlewares = ContiguousArray < Middleware > ( )
23
+ private let serialDispatchScheduler : SerialDispatchQueueScheduler = {
24
+ let serialQueue = DispatchQueue ( label: " com.rxswiftcommunity.rxreduce.serialqueue " )
25
+ return SerialDispatchQueueScheduler . init ( queue: serialQueue, internalSerialQueueName: " com.rxswiftcommunity.rxreduce.serialscheduler " )
26
+ } ( )
27
+
28
+ /// The global State is exposed via an Observable, just like some kind of "middleware".
29
+ /// This global State will trigger a new value after a dispatch(action) has triggered a "onNext" event.
30
+ public lazy var state : Observable < State > = {
31
+ return self . stateSubject. asObservable ( )
32
+ } ( )
26
33
27
34
/// Inits a Store with an initial State
28
35
///
29
36
/// - Parameter state: the initial State
30
37
public init ( withState state: State ) {
31
- self . state = state
38
+
39
+ // Sets the initial State value
40
+ self . stateSubject = BehaviorRelay < State > ( value: state)
32
41
33
42
// We analyze the State children (aka SubState)
34
43
// to be able to check that each of them will be handled
35
44
// by a reducer function (it allows to be sure that if we
36
45
// add a new SubState to the State, there is a reducer in charge
37
46
// of its mutation)
38
- let stateMirror = Mirror ( reflecting: self . state)
47
+ let stateMirror = Mirror ( reflecting: state)
39
48
stateMirror
40
49
. children
41
50
. map { Mirror ( reflecting: $0. value) }
@@ -75,14 +84,6 @@ public final class Store<State: Equatable> {
75
84
self . neededReducersPerSubState [ subStateType] = neededReducerForSubState - 1
76
85
}
77
86
78
- /// Registers a Middleware. Middlewares will be applied in sequence
79
- /// in the same order than their addition
80
- ///
81
- /// - Parameter middleware: The Middleware to add
82
- public func register ( middleware: @escaping Middleware ) {
83
- self . middlewares. append ( middleware)
84
- }
85
-
86
87
/// Dispatches an Action to the registered Reducers.
87
88
/// The Action will first go through the Middlewares and
88
89
/// then through the Reducers producing a mutated State.
@@ -100,18 +101,16 @@ public final class Store<State: Equatable> {
100
101
// every received action is converted to an async action
101
102
return action
102
103
. toAsync ( )
103
- . do ( onNext: { [ unowned self] ( action) in
104
- self . middlewares. forEach ( { [ unowned self] ( middleware) in
105
- middleware ( self . state, action)
106
- } )
107
- } )
108
104
. map { [ unowned self] ( action) -> State in
109
- return self . reducers. reduce ( self . state , { ( currentState, reducer) -> State in
105
+ return self . reducers. reduce ( self . stateSubject . value , { ( currentState, reducer) -> State in
110
106
return reducer ( currentState, action)
111
107
} )
112
- } . do ( onNext: { [ unowned self] ( newState) in
113
- self . state = newState
114
- } ) . distinctUntilChanged ( )
108
+ }
109
+ . do ( onNext: { [ unowned self] ( newState) in
110
+ self . stateSubject. accept ( newState)
111
+ } )
112
+ . distinctUntilChanged ( )
113
+ . subscribeOn ( self . serialDispatchScheduler)
115
114
}
116
115
117
116
/// Dispatches an Action to the registered Mutators but instead of
0 commit comments