/
periodical_executer.js
92 lines (87 loc) · 2.69 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
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
/** section: Language
* class PeriodicalExecuter
*
* Oversees the calling of a particular function periodically.
*
* [[PeriodicalExecuter]] shields you from multiple parallel executions of a
* `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.
*
* ##### Example
*
* new PeriodicalExecuter(function(pe) {
* if (!confirm('Want me to annoy you again later?')) {
* pe.stop();
* }
* }, 5);
**/
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 seconds, to wait in between
* callbacks.
*
* Creates a [[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).
*
* Once a [[PeriodicalExecuter]] is created, it constitues an infinite loop,
* triggering at the given interval until the page unloads. This method lets
* you stop it any time you want.
*
* ##### Example
*
* This will only alert 1, 2 and 3, then the [[PeriodicalExecuter]] stops.
*
* var count = 0;
* new PeriodicalExecuter(function(pe) {
* if (++count > 3) {
* pe.stop();
* } else {
* alert(count);
* }
* }, 1);
**/
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;
}
}
}
});