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