-
Notifications
You must be signed in to change notification settings - Fork 2
/
events.go
259 lines (197 loc) · 6.14 KB
/
events.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
package async
import (
"reflect"
)
/*
Event is a map of functions to use for a single event. The integer is the
frequency of calls that the function should make.
*/
type Event map[reflect.Value]int
/*
Events is a map that is used for containing everything related to the events.
It stores the name of the event, functions for the event, and number of times
the function should be called when the event is triggered.
All you need to do to create an event list is:
events := make(async.Events)
All event commands that return Events can be chained together. For example:
events.On("myevent", func() {
println("Called myevent")
}).On("myevent2", func(msg string) {
fmt.Printf("Called myevent2 with message: %s\n", msg)
}).Emit("myevent").Emit("myevent2", "Testing")
You can return an error from a function and it will be emitted as an error
event. For example:
events.On("error", func(err error) {
fmt.Printf("Error: %s", err)
}).On("myevent", func() error {
return fmt.Errorf("Some error message")
}).Emit("myevent")
It's also easily inheritable by other structures. For example:
type MyStruct struct {
async.Events
}
m := MyStruct{make(async.Events)}
m.On("myevent", func() {
println("Called myevent")
}).Emit("myevent")
When you are defining your event, all function calls within that event must
be in the same format.
For instance, this will work fine:
events.On("myevent", func() {}, func() {})
However, this will NOT work:
events.On("myevent", func() {}, func (msg string) {})
If you were to try this second example, and then try to .Emit("myevent",
"message"), you would get an error from reflect saying that there is too
many arguments for the first function. If you were to try .Emit("myevent"),
you would get an error that there are not enough arguments because of the
second function expecting an argument.
*/
type Events map[string]Event
/*
Clear all events out of the event list. You can supply optional names for
the events to be cleared.
For instance:
events.On("test", func() {}).On("test2", func() {}).Emit("test").Clear("test")
Returns the list of events for chaining commands.
*/
func (e Events) Clear(name ...string) Events {
if name != nil {
for i := 0; i < len(name); i++ {
delete(e, name[i])
}
return e
}
for key := range e {
delete(e, key)
}
return e
}
/*
Emit an event. Arguments are optional. Each event will be ran as a Series.
For example:
events := make(async.Events)
events.On("myevent", func() {
println("Emitted myevent")
})
events.Emit("myevent")
With arguments:
events := make(async.Events)
events.On("myevent", func(msg string) {
fmt.Printf("Message: %s\n", msg)
})
events.Emit("myevent", "Testing")
Returns the list of events for chaining commands.
*/
func (e Events) Emit(name string, args ...interface{}) Events {
var (
routines = make([]Routine, 0)
values = make([]reflect.Value, 0)
)
// If we don't have any events with this name, simply return.
if e.Get(name) == nil {
return e
}
// Reflect all of our arguments for the reflect.Value.Call
for i := 0; i < len(args); i++ {
values = append(values, reflect.ValueOf(args[i]))
}
for fn, freq := range e[name] {
// Decrease frequency
if freq > 0 {
freq--
}
// If the frequency is down to 0, remove the callback from the event
// so that it isn't triggered again.
if freq == 0 {
delete(e[name], fn)
} else {
e[name][fn] = freq
}
// Delete the entire event if all callbacks have been triggered
if len(e[name]) == 0 {
delete(e, name)
}
// Create the routines to pass into Series
routines = append(routines,
func(e Events, fn reflect.Value, values []reflect.Value) Routine {
return func(done Done, args ...interface{}) {
values := fn.Call(values)
for i := 0; i < len(values); i++ {
v := values[i].Interface()
switch v.(type) {
case error:
done(v.(error))
return
}
}
done(nil)
}
}(e, fn, values),
)
}
// Run all of the events in Series
Series(routines, func(err error, args ...interface{}) {
// Only emit the error event if an error was detected. Nothing else needs
// to be done here.
if err != nil {
e.Emit("error", err)
}
})
return e
}
/*
Get Event map of functions and frequencies for the named event. This is just
a convenience function. This data could also be accessed by the normal
mapping methods.
For instance:
fmt.Printf("Events for myevent: %+v\n", e["myevent"])
*/
func (e Events) Get(name string) Event {
return e[name]
}
/*
Length gets the length of the Event map of functions and frequencies for the
named event. This is just a convenience function. This data could also be
accessed by the normal mapping methods.
For instance:
fmt.Printf("Length: %d", len(e["myevent"]))
*/
func (e Events) Length(name string) int {
return len(e.Get(name))
}
/*
On adds an event to be called forever.
This is equal to calling Times with -1 as the number of times to run the
event. More documentation can be found on the Times function.
Returns the list of events for chaining commands.
*/
func (e Events) On(name string, callbacks ...interface{}) Events {
return e.Times(name, -1, callbacks...)
}
/*
Once adds an event to be called only once.
This is equal to calling Times with 1 as the number of times to run the
event. More documentation can be found on the Times function.
Returns the list of events for chaining commands.
*/
func (e Events) Once(name string, callbacks ...interface{}) Events {
return e.Times(name, 1, callbacks...)
}
/*
Times adds an event to be called a number of times. If the number of times for
the function to be called is -1, it will be called until the list is cleared.
Returns the list of events for chaining commands.
*/
func (e Events) Times(name string, times int, callbacks ...interface{}) Events {
// Check to see if the event already exists. If not, create its map.
if e[name] == nil {
e[name] = make(Event)
}
for i := 0; i < len(callbacks); i++ {
// Reflect the function so that we don't have to add function restraints.
fn := reflect.ValueOf(callbacks[i])
// Set the number of times that the event should run.
e[name][fn] = times
}
return e
}