1
1
var Immutable = require ( 'immutable' )
2
- var logging = require ( './logging' )
3
- var ChangeObserver = require ( './change-observer' )
2
+ var createReactMixin = require ( './create-react-mixin' )
3
+ var ReactorState = require ( './reactor/reactor-state' )
4
+ var fns = require ( './reactor/fns' )
5
+ var evaluate = require ( './reactor/evaluate' )
4
6
var Getter = require ( './getter' )
5
7
var KeyPath = require ( './key-path' )
6
- var Evaluator = require ( './evaluator' )
7
- var createReactMixin = require ( './create-react-mixin' )
8
8
9
9
// helper fns
10
10
var toJS = require ( './immutable-helpers' ) . toJS
11
- var toImmutable = require ( './immutable-helpers' ) . toImmutable
12
- var isImmutableValue = require ( './immutable-helpers' ) . isImmutableValue
13
- var each = require ( './utils' ) . each
14
11
15
12
16
13
/**
@@ -29,24 +26,13 @@ class Reactor {
29
26
}
30
27
config = config || { }
31
28
32
- this . debug = ! ! config . debug
29
+ var initialReactorState = new ReactorState ( {
30
+ debug : config . debug
31
+ } )
32
+ this . prevReactorState = initialReactorState
33
+ this . reactorState = initialReactorState
33
34
34
35
this . ReactMixin = createReactMixin ( this )
35
- /**
36
- * The state for the whole cluster
37
- */
38
- this . state = Immutable . Map ( { } )
39
- /**
40
- * Holds a map of id => store instance
41
- */
42
- this . __stores = Immutable . Map ( { } )
43
-
44
- this . __evaluator = new Evaluator ( )
45
- /**
46
- * Change observer interface to observe certain keypaths
47
- * Created after __initialize so it starts with initialState
48
- */
49
- this . __changeObserver = new ChangeObserver ( this . state , this . __evaluator )
50
36
51
37
// keep track of the depth of batch nesting
52
38
this . __batchDepth = 0
@@ -63,7 +49,9 @@ class Reactor {
63
49
* @return {* }
64
50
*/
65
51
evaluate ( keyPathOrGetter ) {
66
- return this . __evaluator . evaluate ( this . state , keyPathOrGetter )
52
+ var evaluateResult = evaluate ( this . reactorState , keyPathOrGetter )
53
+ this . __changed ( evaluateResult . reactorState )
54
+ return evaluateResult . result
67
55
}
68
56
69
57
/**
@@ -98,7 +86,10 @@ class Reactor {
98
86
} else if ( KeyPath . isKeyPath ( getter ) ) {
99
87
getter = Getter . fromKeyPath ( getter )
100
88
}
101
- return this . __changeObserver . onChange ( getter , handler )
89
+ var observeResult = fns . addObserver ( this . reactorState , getter , handler )
90
+ this . __changed ( observeResult . reactorState )
91
+
92
+ return observeResult . unwatchFn
102
93
}
103
94
104
95
@@ -116,10 +107,8 @@ class Reactor {
116
107
this . __isDispatching = true
117
108
}
118
109
119
- var prevState = this . state
120
-
121
110
try {
122
- this . state = this . __handleAction ( prevState , actionType , payload )
111
+ this . __changed ( fns . dispatch ( this . reactorState , actionType , payload ) )
123
112
} catch ( e ) {
124
113
this . __isDispatching = false
125
114
throw e
@@ -128,15 +117,11 @@ class Reactor {
128
117
129
118
if ( this . __batchDepth > 0 ) {
130
119
this . __batchDispatchCount ++
131
- } else {
132
- if ( this . state !== prevState ) {
133
- try {
134
- this . __notify ( )
135
- } catch ( e ) {
136
- this . __isDispatching = false
137
- throw e
138
- }
139
- }
120
+ }
121
+
122
+ try {
123
+ this . __notify ( )
124
+ } finally {
140
125
this . __isDispatching = false
141
126
}
142
127
}
@@ -162,30 +147,16 @@ class Reactor {
162
147
/* eslint-enable no-console */
163
148
var stores = { }
164
149
stores [ id ] = store
165
- this . registerStores ( stores )
150
+ this . batch ( ( ) => {
151
+ this . registerStores ( stores )
152
+ } )
166
153
}
167
154
168
155
/**
169
156
* @param {Store[] } stores
170
157
*/
171
158
registerStores ( stores ) {
172
- each ( stores , ( store , id ) => {
173
- if ( this . __stores . get ( id ) ) {
174
- /* eslint-disable no-console */
175
- console . warn ( 'Store already defined for id = ' + id )
176
- /* eslint-enable no-console */
177
- }
178
-
179
- var initialState = store . getInitialState ( )
180
-
181
- if ( this . debug && ! isImmutableValue ( initialState ) ) {
182
- throw new Error ( 'Store getInitialState() must return an immutable value, did you forget to call toImmutable' )
183
- }
184
-
185
- this . __stores = this . __stores . set ( id , store )
186
- this . state = this . state . set ( id , initialState )
187
- } )
188
-
159
+ this . __changed ( fns . registerStores ( this . reactorState , stores ) )
189
160
this . __notify ( )
190
161
}
191
162
@@ -194,112 +165,45 @@ class Reactor {
194
165
* @return {Object }
195
166
*/
196
167
serialize ( ) {
197
- var serialized = { }
198
- this . __stores . forEach ( ( store , id ) => {
199
- var storeState = this . state . get ( id )
200
- var serializedState = store . serialize ( storeState )
201
- if ( serializedState !== undefined ) {
202
- serialized [ id ] = serializedState
203
- }
204
- } )
205
- return serialized
168
+ return this . reactorState . serialize ( )
206
169
}
207
170
208
171
/**
209
172
* @param {Object } state
210
173
*/
211
174
loadState ( state ) {
212
- var stateToLoad = toImmutable ( { } ) . withMutations ( stateToLoad => {
213
- each ( state , ( serializedStoreState , storeId ) => {
214
- var store = this . __stores . get ( storeId )
215
- if ( store ) {
216
- var storeState = store . deserialize ( serializedStoreState )
217
- if ( storeState !== undefined ) {
218
- stateToLoad . set ( storeId , storeState )
219
- }
220
- }
221
- } )
222
- } )
223
-
224
- this . state = this . state . merge ( stateToLoad )
175
+ this . __changed ( fns . loadState ( this . reactorState , state ) )
225
176
this . __notify ( )
226
177
}
227
178
228
179
/**
229
180
* Resets the state of a reactor and returns back to initial state
230
181
*/
231
182
reset ( ) {
232
- var debug = this . debug
233
- var prevState = this . state
234
-
235
- this . state = Immutable . Map ( ) . withMutations ( state => {
236
- this . __stores . forEach ( ( store , id ) => {
237
- var storeState = prevState . get ( id )
238
- var resetStoreState = store . handleReset ( storeState )
239
- if ( debug && resetStoreState === undefined ) {
240
- throw new Error ( 'Store handleReset() must return a value, did you forget a return statement' )
241
- }
242
- if ( debug && ! isImmutableValue ( resetStoreState ) ) {
243
- throw new Error ( 'Store reset state must be an immutable value, did you forget to call toImmutable' )
244
- }
245
- state . set ( id , resetStoreState )
246
- } )
247
- } )
248
-
249
- this . __evaluator . reset ( )
250
- this . __changeObserver . reset ( this . state )
183
+ var newState = fns . reset ( this . reactorState )
184
+ this . reactorState = newState
185
+ this . prevReactorState = newState
251
186
}
252
187
253
188
/**
254
189
* Notifies all change observers with the current state
255
190
* @private
256
191
*/
257
192
__notify ( ) {
258
- this . __changeObserver . notifyObservers ( this . state )
193
+ if ( this . __batchDepth <= 0 ) {
194
+ // side-effects of notify all observers
195
+ var nextReactorState = fns . notify ( this . prevReactorState , this . reactorState )
196
+
197
+ this . prevReactorState = nextReactorState
198
+ this . reactorState = nextReactorState
199
+ }
259
200
}
260
201
261
202
/**
262
- * Reduces the current state to the new state given actionType / message
263
- * @param {string } actionType
264
- * @param {object|undefined } payload
265
- * @return {Immutable.Map }
203
+ * @param {ReactorState } reactorState
266
204
*/
267
- __handleAction ( state , actionType , payload ) {
268
- return state . withMutations ( state => {
269
- if ( this . debug ) {
270
- logging . dispatchStart ( actionType , payload )
271
- }
272
-
273
- // let each store handle the message
274
- this . __stores . forEach ( ( store , id ) => {
275
- var currState = state . get ( id )
276
- var newState
277
-
278
- try {
279
- newState = store . handle ( currState , actionType , payload )
280
- } catch ( e ) {
281
- // ensure console.group is properly closed
282
- logging . dispatchError ( e . message )
283
- throw e
284
- }
285
-
286
- if ( this . debug && newState === undefined ) {
287
- var errorMsg = 'Store handler must return a value, did you forget a return statement'
288
- logging . dispatchError ( errorMsg )
289
- throw new Error ( errorMsg )
290
- }
291
-
292
- state . set ( id , newState )
293
-
294
- if ( this . debug ) {
295
- logging . storeHandled ( id , currState , newState )
296
- }
297
- } )
298
-
299
- if ( this . debug ) {
300
- logging . dispatchEnd ( state )
301
- }
302
- } )
205
+ __changed ( reactorState ) {
206
+ this . reactorState = reactorState
303
207
}
304
208
305
209
__batchStart ( ) {
0 commit comments