@@ -33,26 +33,34 @@ def method_missing(method, *args)
3333 end
3434
3535 class State
36+
37+ @rendering_level = 0
38+
3639 class << self
3740 attr_reader :current_observer
3841
39- def initialize_states ( object , initial_values )
40- # initialize objects' name/value pairs
42+ def initialize_states ( object , initial_values ) # initialize objects' name/value pairs
4143 states [ object ] . merge! ( initial_values || { } )
4244 end
4345
4446 def get_state ( object , name , current_observer = @current_observer )
45- # get current value of name for object, remember that the current object
46- # depends on this state, current observer can be overriden with last
47- # param
48- new_observers [ current_observer ] [ object ] << name if current_observer &&
49- !new_observers [ current_observer ] [ object ] . include? ( name )
47+ # get current value of name for object, remember that the current object depends on this state,
48+ # current observer can be overriden with last param
49+ new_observers [ current_observer ] [ object ] << name if current_observer && !new_observers [ current_observer ] [ object ] . include? ( name )
5050 states [ object ] [ name ]
5151 end
5252
53- def set_state2 ( object , name , value )
54- # set object's name state to value, tell all observers it has changed.
55- # Observers must implement update_react_js_state
53+ def set_state ( object , name , value , wait_till_thread_completes = nil )
54+ states [ object ] [ name ] = value
55+ if wait_till_thread_completes
56+ notify_observers_after_thread_completes ( object , name , value )
57+ elsif @rendering_level == 0
58+ notify_observers ( object , name , value )
59+ end
60+ value
61+ end
62+
63+ def notify_observers ( object , name , value )
5664 object_needs_notification = object . respond_to? :update_react_js_state
5765 observers_by_name [ object ] [ name ] . dup . each do |observer |
5866 observer . update_react_js_state ( object , name , value )
@@ -61,23 +69,14 @@ def set_state2(object, name, value)
6169 object . update_react_js_state ( nil , name , value ) if object_needs_notification
6270 end
6371
64- def set_state ( object , name , value , delay = nil )
65- states [ object ] [ name ] = value
66- if delay
67- @delayed_updates ||= [ ]
68- @delayed_updates << [ object , name , value ]
69- @delayed_updater ||= after ( 0.001 ) do
70- delayed_updates = @delayed_updates
71- @delayed_updates = [ ]
72- @delayed_updater = nil
73- delayed_updates . each do |object , name , value |
74- set_state2 ( object , name , value )
75- end
76- end
77- else
78- set_state2 ( object , name , value )
72+ def notify_observers_after_thread_completes ( object , name , value )
73+ ( @delayed_updates ||= [ ] ) << [ object , name , value ]
74+ @delayed_updater ||= after ( 0 ) do
75+ delayed_updates = @delayed_updates
76+ @delayed_updates = [ ]
77+ @delayed_updater = nil
78+ delayed_updates . each { |args | notify_observers ( *args ) }
7979 end
80- value
8180 end
8281
8382 def will_be_observing? ( object , name , current_observer )
@@ -88,9 +87,7 @@ def is_observing?(object, name, current_observer)
8887 current_observer && observers_by_name [ object ] [ name ] . include? ( current_observer )
8988 end
9089
91- # should be called after the last after_render callback, currently called
92- # after components render method
93- def update_states_to_observe ( current_observer = @current_observer )
90+ def update_states_to_observe ( current_observer = @current_observer ) # should be called after the last after_render callback, currently called after components render method
9491 raise "update_states_to_observer called outside of watch block" unless current_observer
9592 current_observers [ current_observer ] . each do |object , names |
9693 names . each do |name |
@@ -116,23 +113,21 @@ def remove # call after component is unmounted
116113 current_observers . delete ( @current_observer )
117114 end
118115
119- # wrap all execution that may set or get states in a block so we know
120- # which observer is executing
121- def set_state_context_to ( observer )
116+ def set_state_context_to ( observer , rendering = nil ) # wrap all execution that may set or get states in a block so we know which observer is executing
122117 if `typeof window.reactive_ruby_timing !== 'undefined'`
123118 @nesting_level = ( @nesting_level || 0 ) + 1
124119 start_time = Time . now . to_f
125120 observer_name = ( observer . class . respond_to? ( :name ) ? observer . class . name : observer . to_s ) rescue "object:#{ observer . object_id } "
126121 end
127122 saved_current_observer = @current_observer
128123 @current_observer = observer
124+ @rendering_level += 1 if rendering
129125 return_value = yield
130126 return_value
131127 ensure
132128 @current_observer = saved_current_observer
133- if `typeof window.reactive_ruby_timing !== 'undefined'`
134- @nesting_level = [ 0 , @nesting_level - 1 ] . max
135- end
129+ @rendering_level -= 1 if rendering
130+ @nesting_level = [ 0 , @nesting_level - 1 ] . max if `typeof window.reactive_ruby_timing !== 'undefined'`
136131 return_value
137132 end
138133
@@ -142,7 +137,7 @@ def states
142137
143138 [ :new_observers , :current_observers , :observers_by_name ] . each do |method_name |
144139 define_method ( method_name ) do
145- instance_variable_get ( "@#{ method_name } " ) or
140+ instance_variable_get ( "@#{ method_name } " ) ||
146141 instance_variable_set ( "@#{ method_name } " , Hash . new { |h , k | h [ k ] = Hash . new { |h , k | h [ k ] = [ ] } } )
147142 end
148143 end
0 commit comments