Commit b715609f8d6393dc7cf2fa7be33b256bffcce3e3
map: add option maxTime for incremental updating (avoid tight loop)
Matt McKegg committed on 7/27/2016, 6:28:13 AMParent: 880a92caf2ae2e1a7551e7a500794c09adf5880b
Files changed
map.js | changed |
map.js | |||
---|---|---|---|
@@ -1,9 +1,9 @@ | |||
1 | 1 … | var resolve = require('./resolve') | |
2 | 2 … | ||
3 | 3 … | module.exports = Map | |
4 | 4 … | ||
5 | -function Map (obs, lambda) { | ||
5 … | +function Map (obs, lambda, opts) { | ||
6 | 6 … | var releases = [] | |
7 | 7 … | var live = false | |
8 | 8 … | var lazy = false | |
9 | 9 … | var listeners = [] | |
@@ -14,8 +14,15 @@ | |||
14 | 14 … | var raw = [] | |
15 | 15 … | var values = [] | |
16 | 16 … | var watches = [] | |
17 | 17 … | ||
18 … | + // incremental update | ||
19 … | + var queue = [] | ||
20 … | + var maxTime = null | ||
21 … | + if (opts && opts.maxTime) { | ||
22 … | + maxTime = opts.maxTime | ||
23 … | + } | ||
24 … | + | ||
18 | 25 … | var result = function MutantMap (listener) { | |
19 | 26 … | if (!listener) { | |
20 | 27 … | return getValue() | |
21 | 28 … | } | |
@@ -93,26 +100,22 @@ | |||
93 | 100 … | if (items.length !== getLength(obs)) { | |
94 | 101 … | changed = true | |
95 | 102 … | } | |
96 | 103 … | ||
104 … | + var startedAt = Date.now() | ||
105 … | + | ||
97 | 106 … | for (var i = 0, len = getLength(obs); i < len; i++) { | |
98 | 107 … | var item = get(obs, i) | |
108 … | + var currentItem = items[i] | ||
109 … | + items[i] = item | ||
99 | 110 … | ||
100 | - if (typeof item === 'object') { | ||
101 | - items[i] = item | ||
102 | - raw[i] = lambda(item) | ||
103 | - values[i] = resolve(raw[i]) | ||
104 | - changed = true | ||
105 | - rebind(i) | ||
106 | - } else if (item !== items[i]) { | ||
107 | - items[i] = item | ||
108 | - if (!lastValues.has(item)) { | ||
109 | - lastValues.set(item, lambda(item)) | ||
111 … | + if (typeof item === 'object' || item !== currentItem) { | ||
112 … | + if (maxTime && Date.now() - startedAt > maxTime) { | ||
113 … | + queueUpdateItem(i) | ||
114 … | + } else { | ||
115 … | + updateItem(i) | ||
110 | 116 … | } | |
111 | - raw[i] = lastValues.get(item) | ||
112 | - values[i] = resolve(raw[i]) | ||
113 | 117 … | changed = true | |
114 | - rebind(i) | ||
115 | 118 … | } | |
116 | 119 … | } | |
117 | 120 … | ||
118 | 121 … | if (changed) { | |
@@ -124,8 +127,42 @@ | |||
124 | 127 … | ||
125 | 128 … | return changed | |
126 | 129 … | } | |
127 | 130 … | ||
131 … | + function queueUpdateItem (i) { | ||
132 … | + if (!queue.length) { | ||
133 … | + setImmediate(flushQueue) | ||
134 … | + } | ||
135 … | + if (!~queue.indexOf(i)) { | ||
136 … | + queue.push(i) | ||
137 … | + } | ||
138 … | + } | ||
139 … | + | ||
140 … | + function flushQueue () { | ||
141 … | + var startedAt = Date.now() | ||
142 … | + while (queue.length && (!maxTime || Date.now() - startedAt < maxTime)) { | ||
143 … | + updateItem(queue.pop()) | ||
144 … | + } | ||
145 … | + broadcast() | ||
146 … | + if (queue.length) { | ||
147 … | + setImmediate(flushQueue) | ||
148 … | + } | ||
149 … | + } | ||
150 … | + | ||
151 … | + function updateItem (i) { | ||
152 … | + var item = get(obs, i) | ||
153 … | + if (typeof item === 'object') { | ||
154 … | + raw[i] = lambda(item) | ||
155 … | + } else { | ||
156 … | + if (!lastValues.has(item)) { | ||
157 … | + lastValues.set(item, lambda(item)) | ||
158 … | + } | ||
159 … | + raw[i] = lastValues.get(item) | ||
160 … | + } | ||
161 … | + values[i] = resolve(raw[i]) | ||
162 … | + rebind(i) | ||
163 … | + } | ||
164 … | + | ||
128 | 165 … | function rebind (index) { | |
129 | 166 … | if (watches[index]) { | |
130 | 167 … | watches[index]() | |
131 | 168 … | watches[index] = null |
Built with git-ssb-web