git ssb

1+

Matt McKegg / mutant



Tree: 01e9e1d516a0bcf09d486425ab7cba0f919f5a1a

Files: 01e9e1d516a0bcf09d486425ab7cba0f919f5a1a / lib / lazy-watcher.js

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

Built with git-ssb-web