Skip to content

Commit 34b3492

Browse files
committed
Add example with classes and async execution
1 parent 0abbcea commit 34b3492

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

JavaScript/6-class.js

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
'use strict';
2+
3+
const assert = require('assert').strict;
4+
const { EventEmitter } = require('events');
5+
6+
class Task extends EventEmitter {
7+
constructor(name, time, exec) {
8+
super();
9+
this.name = name;
10+
if (typeof time === 'number') {
11+
this.time = Date.now() + time;
12+
this.set = setInterval;
13+
this.clear = clearInterval;
14+
} else {
15+
this.time = new Date(time).getTime();
16+
this.set = setTimeout;
17+
this.clear = clearTimeout;
18+
}
19+
this.exec = exec;
20+
this.running = false;
21+
this.count = 0;
22+
this.timer = null;
23+
}
24+
get active() {
25+
return !!this.timer;
26+
}
27+
start() {
28+
this.stop();
29+
if (this.running) return false;
30+
const time = this.time - Date.now();
31+
if (time < 0) return false;
32+
this.timer = this.set(() => {
33+
this.run();
34+
}, time);
35+
return true;
36+
}
37+
stop() {
38+
if (!this.active || this.running) return false;
39+
this.clear(this.timer);
40+
this.timer = null;
41+
return true;
42+
}
43+
run() {
44+
if (!this.active || this.running) return false;
45+
this.running = true;
46+
this.exec(err => {
47+
if (err) this.emit('error', err, this);
48+
this.count++;
49+
this.running = false;
50+
});
51+
return true;
52+
}
53+
}
54+
55+
class Scheduler extends EventEmitter {
56+
constructor() {
57+
super();
58+
this.tasks = new Map();
59+
}
60+
task(name, time, exec) {
61+
this.stop(name);
62+
const task = new Task(name, time, exec);
63+
this.tasks.set(name, task);
64+
task.on('error', err => {
65+
this.emit('error', err, task);
66+
});
67+
task.start();
68+
return task;
69+
}
70+
stop(name) {
71+
const task = this.tasks.get(name);
72+
if (task) {
73+
task.stop();
74+
this.tasks.delete(name);
75+
}
76+
}
77+
stopAll() {
78+
for (const name of this.tasks.keys()) {
79+
this.stop(name);
80+
}
81+
}
82+
}
83+
84+
// Tests
85+
86+
const testCreateTask = next => {
87+
const timer = setTimeout(() => {
88+
const err = new Error('Can not create task');
89+
assert.fail(err);
90+
next(err);
91+
}, 200);
92+
93+
const scheduler = new Scheduler();
94+
95+
scheduler.task('name1', '2019-04-16T18:30Z', done => {
96+
done(null, 'task successed');
97+
});
98+
99+
let error = null;
100+
try {
101+
assert.strictEqual(scheduler.tasks.size, 1);
102+
} catch (err) {
103+
error = err;
104+
} finally {
105+
clearTimeout(timer);
106+
next(error);
107+
}
108+
};
109+
110+
const testExecuteTask = next => {
111+
const timer = setTimeout(() => {
112+
const err = new Error('Can not execute task');
113+
assert.fail(err);
114+
next(err);
115+
}, 200);
116+
117+
const scheduler = new Scheduler();
118+
119+
scheduler.task('name1', 100, done => {
120+
let error = null;
121+
try {
122+
assert.ok(scheduler.tasks.get('name1').running);
123+
} catch (err) {
124+
error = err;
125+
} finally {
126+
clearTimeout(timer);
127+
done(null, 'task successed');
128+
next(error);
129+
}
130+
});
131+
};
132+
133+
const testFailedTask = next => {
134+
const timer = setTimeout(() => {
135+
const err = new Error('Task expected to fail');
136+
assert.fail(err);
137+
next(err);
138+
}, 200);
139+
140+
const scheduler = new Scheduler();
141+
142+
scheduler.task('name1', 100, done => {
143+
done(new Error('Task failed'));
144+
});
145+
146+
scheduler.on('error', (err, task) => {
147+
let error = null;
148+
try {
149+
console.dir({ task });
150+
assert.strictEqual(err.message, 'Task failed');
151+
} catch (err) {
152+
error = err;
153+
}
154+
clearTimeout(timer);
155+
next(error);
156+
});
157+
};
158+
159+
// Execute tests
160+
161+
const tests = [
162+
testCreateTask,
163+
testExecuteTask,
164+
testFailedTask,
165+
];
166+
167+
let failed = 0;
168+
const count = tests.length;
169+
const runNext = () => {
170+
if (tests.length === 0) {
171+
console.log(`Total: ${count}; Failed: ${failed}`);
172+
process.exit(failed > 0 ? 1 : 0);
173+
}
174+
const test = tests.shift();
175+
console.log(`Started test: ${test.name}`);
176+
try {
177+
test(err => {
178+
if (err) {
179+
failed++;
180+
console.log(`Failed test: ${test.name}`);
181+
console.log(err);
182+
}
183+
console.log(`Finished test: ${test.name}`);
184+
setTimeout(runNext, 0);
185+
});
186+
} catch (err) {
187+
failed++;
188+
console.log(`Failed test: ${test.name}`);
189+
console.log(err);
190+
setTimeout(runNext, 0);
191+
}
192+
};
193+
194+
runNext();

0 commit comments

Comments
 (0)