-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.js
118 lines (98 loc) · 2.51 KB
/
main.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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
function AsyncObject() {
this.task = null;
this.results = null;
this.error = null;
}
AsyncObject.prototype.setTask = function (task) {
this.task = task;
}
function SingleAsyncObject() {
this.task = null;
this.is_done = 0;
this.results = [];
this.error = null;
}
SingleAsyncObject.prototype = AsyncObject.prototype;
SingleAsyncObject.prototype.setTask = function(task) {
this.task = task;
if(this.is_done != 1) return;
this.is_done = 2;
this.task.next();
}
SingleAsyncObject.prototype.callback = function() {
var self = this;
return function() {
if(arguments.length > 0) {
self.results = Array.prototype.slice.call(arguments, 1);
self.error = arguments[0];
}
self.is_done = 1;
self.setTask(self.task);
}
}
function *callAsync(func) {
var single_async_obj = new SingleAsyncObject();
func(single_async_obj.callback());
yield single_async_obj;
if(single_async_obj.error) {
throw single_async_obj.error;
}
return single_async_obj.results;
}
function *sleep(ms) {
yield* callAsync(function(cb) {
setTimeout(cb, ms);
});
}
function Task(func, cb, err) {
this.iterator = func();
this.callback = cb;
this.err = err;
}
Task.prototype.next = function () {
var self = this;
setTimeout(function() {
var nextValue = {done:false};
try {
while(!nextValue.done) {
nextValue = self.iterator.next();
if(nextValue.value instanceof AsyncObject) {
nextValue.value.setTask(self);
return;
}
}
} catch (err) {
if(self.err) {
self.err(err);
} else {
throw err;
}
return;
}
if(nextValue.done && self.callback) {
setTimeout(function() {
self.callback();
}, 0);
}
}, 0);
}
function spawn(func, cb, err) {
var task = new Task(func, cb, err);
task.next();
}
module.exports = {
AsyncObject: AsyncObject,
SingleAsyncObject: SingleAsyncObject,
spawn: spawn,
callAsync:callAsync,
sleep: sleep
}
Function.prototype.task = function *() {
var func = this;
var self = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
return yield* callAsync(function(cb){
args.push(cb);
func.apply(self, args);
});
}