Class: Volt::Computation

Inherits:
Object show all
Defined in:
lib/volt/reactive/computation.rb

Constant Summary collapse

@@current =
nil
@@flush_queue =
Set.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(computation) ⇒ Computation

Returns a new instance of Computation.

Parameters:

  • the (Proc)

    code to run when the computation needs to compute



17
18
19
20
# File 'lib/volt/reactive/computation.rb', line 17

def initialize(computation)
  @computation   = computation
  @invalidations = []
end

Class Method Details

.currentObject



12
13
14
# File 'lib/volt/reactive/computation.rb', line 12

def self.current
  @@current
end

.current=(val) ⇒ Object



8
9
10
# File 'lib/volt/reactive/computation.rb', line 8

def self.current=(val)
  @@current = val
end

.flush!Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/volt/reactive/computation.rb', line 128

def self.flush!
  fail "Can't flush while in a flush" if @flushing

  @flushing = true
  # clear any timers
  @@timer    = nil

  computations  = @@flush_queue
  @@flush_queue = Set.new

  computations.each(&:compute!)

  @flushing = false
end

.run_without_trackingObject

Run a block without tracking any dependencies



117
118
119
120
121
122
123
124
125
126
# File 'lib/volt/reactive/computation.rb', line 117

def self.run_without_tracking
  previous            = Computation.current
  Computation.current = nil
  begin
    return_value        = yield
  ensure
    Computation.current = previous
  end
  return_value
end

Instance Method Details

#compute!(initial_run = false) ⇒ Object

Runs the computation, called on initial run and when changed!



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/volt/reactive/computation.rb', line 24

def compute!(initial_run=false)
  @invalidated = false

  unless @stopped

    @computing = true
    begin
      run_in do
        if @computation.arity > 0
          # Pass in the Computation so it can be canceled from within
          @computation.call(self)
        else
          @computation.call
        end
      end
    rescue => e
      if initial_run
        # Re-raise if we are in the initial run
        raise
      else
        # Sometimes we get nil as the exception, not sure if thats an opal
        # issue or what.
        if e
          msg = "Exception During Compute: " + e.inspect
          msg += "\n" + e.backtrace.join("\n") if e.respond_to?(:backtrace)
          Volt.logger.error(msg)

          if RUBY_PLATFORM == 'opal'
            `console.log(e);`
          end
        end
      end
    ensure
      @computing = false
    end
  end
end

#invalidate!Object

Calling invalidate removes the computation from all of its dependencies. This keeps its dependencies from invalidating it again.



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/volt/reactive/computation.rb', line 78

def invalidate!
  unless @invalidated
    @invalidated = true

    queue_flush! unless @stopped

    invalidations  = @invalidations
    @invalidations = []

    invalidations.each(&:call)
  end
end

#on_invalidate(&callback) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/volt/reactive/computation.rb', line 62

def on_invalidate(&callback)
  if @invalidated
    # Call invalidate now, since its already invalidated
    # Computation.run_without_tracking do
    queue_flush!
    callback.call
    # end
  else
    # Store the invalidation
    @invalidations << callback
  end
end

#queue_flush!Object



143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/volt/reactive/computation.rb', line 143

def queue_flush!
  @@flush_queue << self

  # If we are in the browser, we queue a flush for the next tick
  # If we are not in the browser, the user must manually flush
  if Volt.in_browser?
    unless @@timer
      # Flush once everything else has finished running
      @@timer = `setImmediate(function() { self.$class()['$flush!'](); })`
    end
  end
end

#run_inObject

Runs in this computation as the current computation, returns the computation



104
105
106
107
108
109
110
111
112
113
114
# File 'lib/volt/reactive/computation.rb', line 104

def run_in
  previous            = Computation.current
  Computation.current = self
  begin
    yield
  ensure
    Computation.current = previous
  end

  self
end

#stopObject

Stop re-run of the computations



92
93
94
95
96
97
# File 'lib/volt/reactive/computation.rb', line 92

def stop
  unless @stopped
    @stopped = true
    invalidate!
  end
end

#stopped?Boolean

Returns:



99
100
101
# File 'lib/volt/reactive/computation.rb', line 99

def stopped?
  @stopped
end