Files: 073f2ca837054c3b04113dd573e1a9e8b0c6ed29 / lib / lazy-watcher.js
2296 bytesRaw
1 | module.exports = function (update, onBind, onUnbind) { |
2 | var lazy = false |
3 | var context = this |
4 | var updating = false |
5 | |
6 | var obj = { |
7 | live: false, |
8 | nextTick: false, |
9 | suspended: false, |
10 | update: update, |
11 | value: null, |
12 | listeners: [], |
13 | |
14 | broadcast: function () { |
15 | if (obj.nextTick) { |
16 | if (!updating) { |
17 | updating = true |
18 | setImmediate(broadcast) |
19 | } |
20 | } else { |
21 | broadcast() |
22 | } |
23 | }, |
24 | |
25 | transaction: function (value, cb) { |
26 | var originalValue = obj.suspended |
27 | obj.suspended = true |
28 | cb(value) |
29 | obj.suspended = originalValue |
30 | obj.broadcast() |
31 | }, |
32 | |
33 | onUpdate: function () { |
34 | if (obj.nextTick) { |
35 | if (!updating) { |
36 | updating = true |
37 | setImmediate(obj.updateAndBroadcast) |
38 | } |
39 | } else { |
40 | obj.updateAndBroadcast() |
41 | } |
42 | }, |
43 | |
44 | updateAndBroadcast: function () { |
45 | updating = false |
46 | if (update.call(context)) { |
47 | broadcast() |
48 | } |
49 | }, |
50 | |
51 | checkUpdated: function () { |
52 | if (!obj.live || lazy || updating) { |
53 | lazy = false |
54 | if (obj.nextTick && obj.live && lazy) { |
55 | obj.onUpdate() // use cached value to make more responsive |
56 | } else { |
57 | update.apply(context) |
58 | } |
59 | } |
60 | }, |
61 | |
62 | getValue: function () { |
63 | obj.checkUpdated.apply(context) |
64 | return obj.value |
65 | }, |
66 | |
67 | addListener: function (listener) { |
68 | if (typeof listener !== 'function') { |
69 | throw new Error('Listeners must be functions.') |
70 | } |
71 | |
72 | obj.listeners.push(listener) |
73 | |
74 | if (!obj.live) { |
75 | obj.live = true |
76 | lazy = true |
77 | onBind.apply(context) |
78 | } |
79 | |
80 | return function release () { |
81 | for (var i = 0, len = obj.listeners.length; i < len; i++) { |
82 | if (obj.listeners[i] === listener) { |
83 | obj.listeners.splice(i, 1) |
84 | break |
85 | } |
86 | } |
87 | if (!obj.listeners.length && obj.live) { |
88 | obj.live = false |
89 | onUnbind.apply(context) |
90 | } |
91 | } |
92 | } |
93 | } |
94 | |
95 | return obj |
96 | |
97 | // scoped |
98 | |
99 | function broadcast () { |
100 | if (!obj.suspended) { |
101 | var cachedListeners = obj.listeners.slice(0) |
102 | for (var i = 0, len = cachedListeners.length; i < len; i++) { |
103 | cachedListeners[i](obj.value) |
104 | } |
105 | } |
106 | } |
107 | } |
108 |
Built with git-ssb-web