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



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/volt/reactive/computation.rb', line 108

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



97
98
99
100
101
102
103
104
105
106
# File 'lib/volt/reactive/computation.rb', line 97

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!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
# File 'lib/volt/reactive/computation.rb', line 24

def compute!
  @invalidated = false

  unless @stopped

    @computing = true
    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
    @computing = false
  end
end

#invalidate!Object

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



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/volt/reactive/computation.rb', line 58

def invalidate!
  unless @invalidated
    @invalidated = true

    queue_flush! unless @stopped

    invalidations  = @invalidations
    @invalidations = []

    invalidations.each(&:call)
  end
end

#on_invalidate(&callback) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/volt/reactive/computation.rb', line 42

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



123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/volt/reactive/computation.rb', line 123

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



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/volt/reactive/computation.rb', line 84

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



72
73
74
75
76
77
# File 'lib/volt/reactive/computation.rb', line 72

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

#stopped?Boolean

Returns:



79
80
81
# File 'lib/volt/reactive/computation.rb', line 79

def stopped?
  @stopped
end