/
periodical_executer.js
67 lines (62 loc) · 2.01 KB
/
periodical_executer.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
/** section: Language
* class PeriodicalExecuter
*
* A class that oversees the calling of a particular function periodically.
*
* `PeriodicalExecuter` shields you from multiple parallel executions of the
* `callback` function, should it take longer than the given interval to
* execute.
*
* This is especially useful if you use one to interact with the user at
* given intervals (e.g. use a prompt or confirm call): this will avoid
* multiple message boxes all waiting to be actioned.
**/
var PeriodicalExecuter = Class.create({
/**
* new PeriodicalExecuter(callback, frequency)
* - callback (Function): the function to be executed at each interval.
* - frequency (Number): the amount of time, in sections, to wait in between
* callbacks.
*
* Creates an `PeriodicalExecuter`.
**/
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
this.registerCallback();
},
registerCallback: function() {
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
execute: function() {
this.callback(this);
},
/**
* PeriodicalExecuter#stop() -> undefined
*
* Stops the periodical executer (there will be no further triggers).
**/
stop: function() {
if (!this.timer) return;
clearInterval(this.timer);
this.timer = null;
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
// IE doesn't support `finally` statements unless all errors are caught.
// We mimic the behaviour of `finally` statements by duplicating code
// that would belong in it. First at the bottom of the `try` statement
// (for errorless cases). Secondly, inside a `catch` statement which
// rethrows any caught errors.
try {
this.currentlyExecuting = true;
this.execute();
this.currentlyExecuting = false;
} catch(e) {
this.currentlyExecuting = false;
throw e;
}
}
}
});