git ssb

1+

Matt McKegg / mutant



Commit 2244524e466413910788cad98baa61df4f340866

computed: resolve and broadcast inner value if observable

Matt McKegg committed on 7/15/2016, 3:04:19 AM
Parent: ec39f72902c3a64aa9841e339bd53cf60182953c

Files changed

computed.jschanged
computed.jsView
@@ -1,18 +1,30 @@
11 /* 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
2 +// - doesn't start watching observables until itself is watched, and then releases if unwatched
3 +// - avoids memory/watcher leakage
4 +// - attaches to inner observables if these are returned from value
5 +// - doesn't broadcast if value is same as last value (and is `value type` or observable, can't make assuptions about reference types)
46
57 var resolve = require('./resolve')
8 +var isObservable = require('./is-observable')
69
710 module.exports = computed
811
912 function computed (observables, lambda) {
13 + if (!Array.isArray(observables)) {
14 + observables = [observables]
15 + }
16 +
1017 var values = []
1118 var releases = []
1219 var computedValue = null
20 +
21 + var inner = null
22 + var releaseInner = null
23 +
1324 var live = false
1425 var lazy = false
26 + var initialized = false
1527 var listeners = []
1628
1729 var result = function (listener) {
1830 if (!listener) {
@@ -49,16 +61,25 @@
4961 if (typeof observables[i] === 'function') {
5062 releases.push(observables[i](onUpdate))
5163 }
5264 }
65 + if (inner) {
66 + releaseInner = inner(onInnerUpdate)
67 + }
5368 live = true
5469 lazy = true
5570 }
5671 }
5772
5873 function unlisten () {
5974 if (live) {
6075 live = false
76 +
77 + if (releaseInner) {
78 + releaseInner()
79 + releaseInner = null
80 + }
81 +
6182 while (releases.length) {
6283 releases.pop()()
6384 }
6485 }
@@ -73,18 +94,42 @@
7394 values[i] = newValue
7495 }
7596 }
7697
77- if (changed) {
98 + if (changed || !initialized) {
99 + initialized = true
78100 var newComputedValue = lambda.apply(null, values)
79- if (newComputedValue !== computedValue || typeof newComputedValue === 'object') {
80- computedValue = newComputedValue
101 + if (newComputedValue !== computedValue || (typeof newComputedValue === 'object' && !isObservable(newComputedValue))) {
102 + if (releaseInner) {
103 + releaseInner()
104 + inner = releaseInner = null
105 + }
106 +
107 + if (isObservable(newComputedValue)) {
108 + // handle returning observable from computed
109 + computedValue = newComputedValue()
110 + inner = newComputedValue
111 + if (live) {
112 + releaseInner = inner(onInnerUpdate)
113 + }
114 + } else {
115 + computedValue = newComputedValue
116 + }
81117 return true
82118 }
83119 }
84120 return false
85121 }
86122
123 + function onInnerUpdate (value) {
124 + if (value !== computedValue || typeof newComputedValue === 'object') {
125 + computedValue = value
126 + for (var i = 0, len = listeners.length; i < len; i++) {
127 + listeners[i](computedValue)
128 + }
129 + }
130 + }
131 +
87132 function onUpdate () {
88133 if (update()) {
89134 for (var i = 0, len = listeners.length; i < len; i++) {
90135 listeners[i](computedValue)

Built with git-ssb-web