git ssb

1+

Matt McKegg / mutant



Tree: e75defac47630de9da141ca0ca89cba54a030464

Files: e75defac47630de9da141ca0ca89cba54a030464 / computed.js

2171 bytesRaw
1/* A lazy binding take on computed */
2// doesn't start watching observables until itself is watched, and then releases if unwatched
3// avoids memory/watcher leakage
4
5var resolve = require('./resolve')
6
7module.exports = computed
8
9function computed (observables, lambda) {
10 var values = []
11 var releases = []
12 var computedValue = null
13 var live = false
14 var lazy = false
15 var listeners = []
16
17 var result = function (listener) {
18 if (!listener) {
19 return getValue()
20 }
21
22 if (typeof listener !== 'function') {
23 throw new Error('Listeners must be functions.')
24 }
25
26 listeners.push(listener)
27 listen()
28
29 return function remove () {
30 for (var i = 0, len = listeners.length; i < len; i++) {
31 if (listeners[i] === listener) {
32 listeners.splice(i, 1)
33 break
34 }
35 }
36 if (!listeners.length) {
37 unlisten()
38 }
39 }
40 }
41
42 return result
43
44 // scoped
45
46 function listen () {
47 if (!live) {
48 for (var i = 0, len = observables.length; i < len; i++) {
49 if (typeof observables[i] === 'function') {
50 releases.push(observables[i](onUpdate))
51 }
52 }
53 live = true
54 lazy = true
55 }
56 }
57
58 function unlisten () {
59 if (live) {
60 live = false
61 while (releases.length) {
62 releases.pop()()
63 }
64 }
65 }
66
67 function update () {
68 var changed = false
69 for (var i = 0, len = observables.length; i < len; i++) {
70 var newValue = resolve(observables[i])
71 if (newValue !== values[i] || typeof newValue === 'object') {
72 changed = true
73 values[i] = newValue
74 }
75 }
76
77 if (changed) {
78 var newComputedValue = lambda.apply(null, values)
79 if (newComputedValue !== computedValue || typeof newComputedValue === 'object') {
80 computedValue = newComputedValue
81 return true
82 }
83 }
84 return false
85 }
86
87 function onUpdate () {
88 if (update()) {
89 for (var i = 0, len = listeners.length; i < len; i++) {
90 listeners[i](computedValue)
91 }
92 }
93 }
94
95 function getValue () {
96 if (!live || lazy) {
97 lazy = false
98 update()
99 }
100 return computedValue
101 }
102}
103

Built with git-ssb-web