welsonjs/lib/task.js

248 lines
5.8 KiB
JavaScript
Raw Normal View History

2021-06-22 21:04:11 +00:00
//////////////////////////////////////////////////////////////////////////////////
2021-06-23 05:31:39 +00:00
// Task API (Time-sharing based `async`, `setTimeout`, `setInterval`, `Promise` implementation in WSH.js)
2021-06-22 21:04:11 +00:00
/////////////////////////////////////////////////////////////////////////////////
2021-06-23 03:03:44 +00:00
/* // example:
* // var TASK = require("lib/task");
2021-06-23 03:05:39 +00:00
* // var taskQueue = TASK.createTaskQueue();
2021-07-05 16:20:39 +00:00
* // TASK.putTask(queue, TASK.createTask(function(task, a, b, c) { console.log(a + b + c); sleep(100); }, [1, 2, 3]))
* // .then(TASK.createTask(function(task, a, b, c) { console.log(a + b + c); sleep(200); }, [4, 5, 6]))
* // .then(TASK.createTask(function(task, a, b, c) { console.log(a + b + c); sleep(300); }, [7, 8, 9]))
2021-06-23 03:08:38 +00:00
* // ;
2021-07-05 16:20:39 +00:00
* // TASK.putTask(queue, TASK.createTask(function(task, a, b, c) { console.log(a + b + c); sleep(100); }, [3, 2, 1])
* // .then(TASK.createTask(function(task, a, b, c) { console.log(a + b + c); sleep(200); }, [6, 5, 4]))
* // .then(TASK.createTask(function(task, a, b, c) { TASK.stop(); console.log(a + b + c); sleep(300); }, [9, 8, 7]))
2021-06-23 03:03:44 +00:00
* // ;
2021-06-23 03:05:39 +00:00
* // taskQueue.run();
2021-06-23 03:03:44 +00:00
*/
2021-07-05 16:20:39 +00:00
var Task = function(f, params) {
2021-06-22 21:04:11 +00:00
this.f = f;
this.params = params;
this.nextTask = null;
2021-07-19 18:09:24 +00:00
this.failTask = null;
2021-07-16 11:10:27 +00:00
this.when = 0;
this.delay = 0;
2021-07-16 16:27:22 +00:00
this.callCount = 0;
2021-07-19 18:09:24 +00:00
2021-06-22 21:04:11 +00:00
this.setNextTask = function(task) {
this.nextTask = task;
2021-07-19 18:09:24 +00:00
return this;
};
this.setFailTask = function(task) {
this.failTask = task;
return this;
2021-06-24 18:43:54 +00:00
};
2021-07-05 16:20:39 +00:00
this.setWhen = function(when) {
this.when = when;
2021-07-16 11:10:27 +00:00
return this;
};
this.setDelay = function(delay) {
this.delay = delay;
return this;
2021-07-05 16:20:39 +00:00
};
2021-07-16 16:27:22 +00:00
this.upCallCount = function() {
this.callCount++;
return this;
};
2021-07-16 17:05:39 +00:00
this.resetCount = function() {
this.callCount = 0;
2021-07-19 18:09:24 +00:00
return this;
2021-07-16 17:05:39 +00:00
};
2021-06-22 21:04:11 +00:00
};
var TaskQueue = function() {
this._task = null;
2021-06-23 02:13:32 +00:00
this._keepalive = true;
2021-06-22 21:04:11 +00:00
this.queue = [];
2021-07-19 18:09:24 +00:00
2021-07-16 11:10:27 +00:00
this.put = function(task, delay) {
var now = new Date();
2021-06-22 21:04:11 +00:00
try {
2021-07-16 11:10:27 +00:00
task.setWhen(now.getTime());
if (typeof(delay) !== "undefined") {
task.setDelay(delay);
}
2021-06-22 21:04:11 +00:00
this._task = task;
2021-07-16 11:10:27 +00:00
this.queue.push(task);
2021-06-22 21:04:11 +00:00
} catch(e) {
console.error("TaskQueue.put exception: " + e.message);
}
return this;
};
this.get = function() {
var task = null;
2021-07-05 16:20:39 +00:00
var now = new Date();
2021-06-23 05:54:47 +00:00
2021-06-22 21:04:11 +00:00
try {
if (this.queue.length > 0) {
2021-07-16 02:09:14 +00:00
var delta = this.queue.map(function(task) {
2021-07-16 11:10:27 +00:00
return task.when + task.delay - now.getTime();
2021-07-16 02:09:14 +00:00
});
var i = delta.indexOf(Math.min.apply(Math, delta));
2021-07-16 11:10:27 +00:00
var d = this.queue[i].when + this.queue[i].delay - now.getTime();
if (i > -1 && d <= 0) {
2021-07-16 16:27:22 +00:00
console.log("Task", i, d);
2021-07-16 02:09:14 +00:00
task = this.queue.splice(i, 1)[0];
2021-07-05 16:20:39 +00:00
}
2021-06-22 21:04:11 +00:00
}
} catch(e) {
console.error("TaskQueue.get: " + e.message);
}
2021-07-16 16:27:22 +00:00
2021-06-22 21:04:11 +00:00
return task;
};
this.next = function() {
var result = null;
2021-06-23 05:54:47 +00:00
2021-06-22 21:04:11 +00:00
try {
var task = this.get();
if (task != null) {
try {
2021-07-16 16:27:22 +00:00
result = task.f.apply(Task, [task].concat(task.params));
2021-07-05 16:20:39 +00:00
if (task.nextTask != null) {
2021-07-16 11:10:27 +00:00
this.put(task.nextTask, task.nextTask.delay);
2021-07-05 16:20:39 +00:00
}
2021-07-16 16:27:22 +00:00
task.upCallCount(); // 호출 횟수 기록
2021-06-22 21:04:11 +00:00
} catch (e) {
console.error("Task exception: " + e.message);
2021-07-05 13:10:25 +00:00
console.error("task.f: " + typeof(task.f));
console.error("task.params: " + typeof(task.params));
2021-07-19 18:09:24 +00:00
// 태스크 개별 오류 처리
if (task.failTask) {
this.put(task.failTask, 0);
}
2021-06-22 21:04:11 +00:00
}
}
} catch(e) {
console.error("TaskQueue.next: " + e.message);
}
return result;
};
2021-07-16 11:10:27 +00:00
this.then = function(task, delay) {
2021-06-22 21:04:11 +00:00
try {
2021-07-16 11:10:27 +00:00
if (typeof(delay) !== "undefined") {
task.setDelay(delay);
}
2021-06-22 21:04:11 +00:00
this._task.setNextTask(task);
this._task = task;
return this;
} catch(e) {
console.error("TaskQueue.then: " + e.message);
2021-07-16 11:10:27 +00:00
console.error(this._task);
2021-06-22 21:04:11 +00:00
}
};
2021-06-23 02:13:32 +00:00
this.run = function() {
2021-06-23 02:15:18 +00:00
this._keepalive = true;
2021-06-23 02:13:32 +00:00
while(this._keepalive) {
this.next();
2021-06-23 05:20:45 +00:00
sleep(1);
2021-06-23 02:13:32 +00:00
}
};
this.stop = function() {
this._keepalive = false;
};
2021-06-22 21:04:11 +00:00
};
2021-06-23 02:21:07 +00:00
exports.createTaskQueue = function() {
2021-06-22 21:04:11 +00:00
return new TaskQueue();
};
2021-07-19 18:09:24 +00:00
exports.createTask = function(f, params, failTask) {
2021-06-22 21:04:11 +00:00
try {
2021-07-19 18:09:24 +00:00
return (new Task(f, params)).setFailTask(failTask);
2021-06-22 21:04:11 +00:00
} catch(e) {
2021-06-23 02:57:38 +00:00
console.error("createTask exception: " + e.message);
2021-06-22 21:04:11 +00:00
}
};
2021-07-16 11:10:27 +00:00
exports.putTask = function(q, task, delay) {
2021-06-22 21:04:11 +00:00
try {
2021-07-05 13:11:17 +00:00
if (q instanceof TaskQueue && task instanceof Task) {
2021-07-16 11:10:27 +00:00
return q.put(task, delay);
2021-06-22 21:04:11 +00:00
}
} catch(e) {
console.error("putTask exception: " + e.message);
}
};
exports.nextTask = function(q) {
try {
return q.next();
} catch(e) {
console.error("nextTask exception: " + e.message);
}
};
2021-06-23 02:13:32 +00:00
exports.run = function(q) {
q.run();
};
2021-06-23 02:18:42 +00:00
exports.stop = function(q) {
q.stop();
2021-06-23 05:20:45 +00:00
};
2021-07-28 04:32:25 +00:00
////////////////////////////////////////////////////
// START Global functions
////////////////////////////////////////////////////
var __taskQueue__ = new TaskQueue();
function setTimeout(f, delay) {
var params = (arguments.length > 2 ? arguments.slice(2) : []);
var task = new Task(f, delay);
__taskQueue__.put(task);
}
// TODO: compatiblity with clearInterval()
function setInterval(f, delay) {
var params = (arguments.length > 2 ? arguments.slice(2) : []);
var task = new Task(f, delay);
task.setNextTask(task);
__taskQueue__.put(task);
}
2021-07-28 04:49:04 +00:00
function Promise(executor) {
this.length = 1;
this.executor = executor;
this.all = function(iterable) {
// todo
};
this.race = function(iterable) {
// todo
};
this.reject = function(reason) {
// todo
};
this.resolve = function(reason) {
// todo
};
this.then = function(successCallback, failureCallback) {
// todo
};
this.catch = function(failureCallback) {
// todo
};
this.executor(this.resolve, this.reject);
}
2021-07-28 04:32:25 +00:00
exports.__taskQueue__ = __taskQueue__;
exports.setTimeout = setTimeout;
exports.setInterval = setInterval;
2021-07-28 04:49:04 +00:00
exports.Promise = Promise;
2021-07-28 04:32:25 +00:00
////////////////////////////////////////////////////
// END Global functions
////////////////////////////////////////////////////
2021-07-16 16:27:22 +00:00
exports.Task = Task;
exports.TaskQueue = TaskQueue;
2021-07-16 11:10:27 +00:00
exports.VERSIONINFO = "Task Module (task.js) version 0.2";
2021-06-24 18:43:54 +00:00
exports.global = global;
exports.require = require;