UNPKG

5.03 kBtext/coffeescriptView Raw
1# Import
2{EventEmitter} = require('events')
3typeChecker = require('typechecker')
4
5
6# =====================================
7# Event & EventSystem
8# Extends the EventEmitterEnhanced with support for:
9# - blocking events
10# - start and finish events
11
12# Event
13class Event
14 # The name of the event
15 name: null
16 # Is the event currently locked?
17 locked: false
18 # Has the event finished running?
19 finished: false
20 # Apply our name on construction
21 constructor: ({@name}) ->
22
23# EventSystem
24class EventSystem extends EventEmitter
25 # Event store
26 # initialised in our event function to prevent javascript reference problems
27 _eventSystemEvents: null
28
29 # Fetch the event object for the event
30 event: (eventName) ->
31 # Prepare
32 @_eventSystemEvents or= {}
33 # Return the fetched event, create it if it doesn't exist already
34 @_eventSystemEvents[eventName] or= new Event(eventName)
35
36 # Lock the event
37 # next(err)
38 lock: (eventName, next) ->
39 # Grab the event
40 event = @event eventName
41 # Grab a lock on the event
42 if event.locked is false
43 # Place the lock
44 event.locked = true
45 # Trigger our event
46 # then fire our callback
47 try
48 @emit eventName+':locked'
49 catch err
50 next(err)
51 return @
52 finally
53 next()
54 else
55 # Wait until the current task has finished
56 @onceUnlocked eventName, (err) =>
57 return next(err) if err
58 # Then try again
59 @lock eventName, next
60
61 # Chain
62 @
63
64 # Unlock the event
65 # next(err)
66 unlock: (eventName, next) ->
67 # Grab the event
68 event = @event eventName
69 # Release the lock
70 event.locked = false
71 # Trigger our event
72 # then fire our callback
73 try
74 @emit eventName+':unlocked'
75 catch err
76 next(err)
77 return @
78 finally
79 next()
80 # Chain
81 @
82
83 # Start our event
84 # 1. Performs a lock
85 # 2. Sets event's finished flag to false
86 # 3. Fires callback
87 # next(err)
88 start: (eventName, next) ->
89 # Grab a locak
90 @lock eventName, (err) =>
91 # Error?
92 return next(err) if err
93 # Grab the event
94 event = @event eventName
95 # Set as started
96 event.finished = false
97 # Trigger our event
98 # then fire our callback
99 try
100 @emit eventName+':started'
101 catch err
102 next(err)
103 return @
104 finally
105 next()
106 # Chain
107 @
108
109 # Finish, alias for finished
110 finish: (args...) ->
111 @finished.apply(@,args)
112
113 # Finished our event
114 # 1. Sets event's finished flag to true
115 # 2. Unlocks the event
116 # 3. Fires callback
117 # next(err)
118 finished: (eventName, next) ->
119 # Grab the event
120 event = @event eventName
121 # Set as finished
122 event.finished = true
123 # Unlock
124 @unlock eventName, (err) =>
125 # Error?
126 return next(err) if err
127 # Trigger our event
128 # then fire our callback
129 try
130 @emit eventName+':finished'
131 catch err
132 next(err)
133 return @
134 finally
135 next()
136 # Chain
137 @
138
139 # Run one time once an event has unlocked
140 # next(err)
141 onceUnlocked: (eventName, next) ->
142 # Grab the event
143 event = @event eventName
144 # Check lock status
145 if event.locked
146 # Wait until our event has unlocked to fire the callback
147 @once eventName+':unlocked', next
148 else
149 # Fire our callback now
150 next()
151 # Chain
152 @
153
154 # Run one time once an event has finished
155 # next(err)
156 onceFinished: (eventName, next) ->
157 # Grab the event
158 event = @event eventName
159 # Check finish status
160 if event.finished
161 # Fire our callback now
162 next()
163 else
164 # Wait until our event has finished to fire the callback
165 @once eventName+':finished', next
166 # Chain
167 @
168
169 # Run every time an event has finished
170 # next(err)
171 whenFinished: (eventName, next) ->
172 # Grab the event
173 event = @event eventName
174 # Check finish status
175 if event.finished
176 # Fire our callback now
177 next()
178 # Everytime our even has finished, fire the callback
179 @on eventName+':finished', next
180 # Chain
181 @
182
183 # When, alias for on
184 when: (args...) ->
185 @on.apply(@,args)
186
187 # Block an event from running
188 # next(err)
189 block: (eventNames, next) ->
190 # Ensure array
191 unless typeChecker.isArray(eventNames)
192 if typeChecker.isString(eventNames)
193 eventNames = eventNames.split(/[,\s]+/g)
194 else
195 err = new Error('Unknown eventNames type')
196 return next(err)
197 total = eventNames.length
198 done = 0
199 # Block these events
200 for eventName in eventNames
201 @lock eventName, (err) ->
202 # Error?
203 if err
204 done = total
205 return next(err)
206 # Increment
207 done++
208 if done is total
209 next()
210 # Chain
211 @
212
213 # Unblock an event from running
214 # next(err)
215 unblock: (eventNames, next) ->
216 # Ensure array
217 unless typeChecker.isArray(eventNames)
218 if typeChecker.isString(eventNames)
219 eventNames = eventNames.split /[,\s]+/g
220 else
221 err = new Error('Unknown eventNames type')
222 return next(err)
223 total = eventNames.length
224 done = 0
225 # Block these events
226 for eventName in eventNames
227 @unlock eventName, (err) ->
228 # Error?
229 if err
230 done = total
231 return next(err)
232 # Increment
233 done++
234 if done is total
235 next()
236 # Chain
237 @
238
239
240
241# =====================================
242# Export
243
244module.exports = {Event,EventSystem}