/
State.js
101 lines (89 loc) · 2.21 KB
/
State.js
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
/* Simple state machine.
*
* Extend from Emitter.
*
* ### constructor
*
* |Name |Desc |
* |-------|----------------------|
* |initial|Initial state |
* |events |Events to change state|
*
* ### is
*
* Check current state.
*
* |Name |Desc |
* |------|----------------------------------------|
* |state |State to check |
* |return|True if current state equals given value|
*/
/* example
* const state = new State('empty', {
* load: { from: 'empty', to: 'pause' },
* play: { from: 'pause', to: 'play' },
* pause: { from: ['play', 'empty'], to: 'pause' },
* unload: { from: ['play', 'pause'], to: 'empty' }
* });
*
* state.is('empty'); // -> true
* state.load();
* state.is('pause'); // -> true
* state.on('play', function(src) {
* console.log(src); // -> 'eustia'
* });
* state.on('error', function(err, event) {
* // Error handler
* });
* state.play('eustia');
*/
/* module
* env: all
*/
/* typescript
* export declare class State extends Emitter {
* constructor(initial: string, events: any);
* is(state: string): boolean;
* [event: string]: any;
* }
*/
_('Emitter each some toArr');
exports = Emitter.extend({
className: 'State',
initialize(initial, events) {
this.callSuper(Emitter, 'initialize');
this.current = initial;
const self = this;
each(events, function(event, key) {
self[key] = buildEvent(key, event);
});
},
is(state) {
return this.current === state;
}
});
function buildEvent(name, event) {
const from = toArr(event.from);
const to = event.to;
return function() {
const args = toArr(arguments);
args.unshift(name);
const hasEvent = some(
from,
function(val) {
return this.current === val;
},
this
);
if (hasEvent) {
this.current = to;
this.emit.apply(this, args);
} else {
this.emit(
'error',
new Error(this.current + ' => ' + to + ' error'),
name
);
}
};
}