-
Notifications
You must be signed in to change notification settings - Fork 0
/
TimerTransition.ts
78 lines (70 loc) · 1.71 KB
/
TimerTransition.ts
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
import {
State,
Automaton,
Transition,
TransitionFunction,
Signal,
} from "./Automaton";
/**
* A class that implements a time-based transition.
*/
class TimerTransition extends Transition {
/**
* Returns [[Signal]] that is triggered when the corresponding timer fires.
*
* @param ms - timer value in milliseconds
*/
public static signal(ms: number): Signal {
return "_$timer" + ms;
}
/**
* Result of `setTimeout`
*/
private timer: any;
constructor(
state: State,
implementation: TransitionFunction,
private ms: number,
) {
super(state, TimerTransition.signal(ms), implementation);
}
public onConditionsMet(stateMachine: Automaton): void {
super.onConditionsMet(stateMachine);
this.timer = setTimeout(this.handleTimer.bind(this, stateMachine), this.ms);
}
public onConditionsUnmet(stateMachine: Automaton): void {
super.onConditionsUnmet(stateMachine);
clearTimeout(this.timer);
}
private handleTimer(stateMachine: Automaton) {
stateMachine.transition(TimerTransition.signal(this.ms));
}
}
/**
* Creates a [[Transition]] that automatically occurs in a timeout.
*
*```javascript
*import {automaton, timer, INITIAL} from 'automatons'
*
*const stateMachine = automaton([
* timer(INITIAL, 1000, 'second passed'),
*]);
*
*stateMachine.state === INITIAL;
*```
* As one second passes:
*```javascript
*stateMachine.state === 'second passed'
*```
*
* @param state - state that makes the transition possible and starts the timer
* @param ms - timeout in milliseconds
* @param implementation - transition function
*/
export function timer(state: State, ms: number, implementation: TransitionFunction): Transition {
return new TimerTransition(
state,
implementation,
ms,
);
}