UNPKG

async-promise

Version:

Asynchronous coordination primitives for JavaScript and TypeScript

195 lines (194 loc) 7.42 kB
var list_1 = require('./list'); var SCHEDULER_KIND = typeof setImmediate === "function" ? "setImmediate" : typeof msSetImmediate === "function" ? "msSetImmediate" : typeof MessageChannel === "function" ? "MessageChannel" : typeof process === "object" && typeof process.nextTick === "function" ? "process.nextTick" : typeof setTimeout === "function" ? "setTimeout" : "unknown"; var Task = (function () { function Task(onexecute, oncancel) { if (typeof onexecute !== "function") throw new TypeError(); this._onexecute = onexecute; this._oncancel = oncancel; } Task.prototype.execute = function () { var onexecute = this._onexecute; this._onexecute = undefined; this._oncancel = undefined; if (onexecute != undefined) { onexecute(); } }; Task.prototype.cancel = function (reason) { var oncancel = this._oncancel; this._onexecute = undefined; this._oncancel = undefined; if (oncancel != undefined) { oncancel(reason); } }; return Task; })(); exports.Task = Task; (function (TaskSchedulerPriority) { TaskSchedulerPriority[TaskSchedulerPriority["none"] = -1] = "none"; TaskSchedulerPriority[TaskSchedulerPriority["background"] = 0] = "background"; TaskSchedulerPriority[TaskSchedulerPriority["send"] = 1] = "send"; })(exports.TaskSchedulerPriority || (exports.TaskSchedulerPriority = {})); var TaskSchedulerPriority = exports.TaskSchedulerPriority; var TaskScheduler = (function () { function TaskScheduler() { var _this = this; this._backgroundQueue = new list_1.LinkedList(); this._sendQueue = new list_1.LinkedList(); this._marker = new list_1.LinkedListNode(); this._marked = false; this._ontick = function () { return _this.tick(); }; if (SCHEDULER_KIND === "MessageChannel") { this._channel = new MessageChannel(); this._channel.port2.onmessage = this._ontick; } } Object.defineProperty(TaskScheduler, "default", { get: function () { return this._default || (this._default = new this()); }, enumerable: true, configurable: true }); Object.defineProperty(TaskScheduler.prototype, "max", { get: function () { if (this._sendQueue.size > 0) { return TaskSchedulerPriority.send; } else if (this._backgroundQueue.size > 0) { return TaskSchedulerPriority.background; } return TaskSchedulerPriority.none; }, enumerable: true, configurable: true }); TaskScheduler.prototype.enqueue = function (priority, onexecute, oncancel) { var _this = this; this.requestTick(); var queue = this.getQueue(priority); var node = new list_1.LinkedListNode(new Task(function () { return _this.onexecute(priority, node, onexecute); }, function (reason) { return _this.oncancel(priority, node, oncancel, reason); })); queue.push(node); return node.value; }; TaskScheduler.prototype.delay = function (msec, onexecute, oncancel) { var _this = this; var handle; var task = new Task(function () { return _this.ondelayexecute(handle, onexecute); }, function (reason) { return _this.ondelaycancel(handle, oncancel, reason); }); handle = setTimeout(function () { return task.execute(); }); return task; }; TaskScheduler.prototype.requestTick = function () { if (this._state !== "requested") { this._state = "requested"; switch (SCHEDULER_KIND) { case "setTimeout": this._handle = setTimeout(this._ontick, 0); break; case "setImmediate": this._handle = setImmediate(this._ontick); break; case "msSetImmediate": this._handle = msSetImmediate(this._ontick); break; case "nextTick": process.nextTick(this._ontick); break; case "postMessage": this._channel.port1.postMessage(); break; } } }; TaskScheduler.prototype.resetTick = function () { if (this._state === "requested") { this._state = "reset"; switch (SCHEDULER_KIND) { case "setTimeout": clearTimeout(this._handle); break; case "setImmediate": clearImmediate(this._handle); break; case "msSetImmediate": msClearImmediate(this._handle); break; } this._handle = undefined; } }; TaskScheduler.prototype.tick = function () { var state = this._state; this._state = undefined; this._handle = undefined; if (state === "requested") { if (!this._marked) { this._backgroundQueue.push(this._marker); this._marked = true; } var completed = false; try { var task = this.dequeue(); while (task) { if (task === this._marker) { this._marked = false; break; } task.value.execute(); task = this.dequeue(); } completed = true; } finally { if (!completed) { this.requestTick(); } } } }; TaskScheduler.prototype.getQueue = function (priority) { switch (priority) { case TaskSchedulerPriority.background: return this._backgroundQueue; case TaskSchedulerPriority.send: return this._sendQueue; } }; TaskScheduler.prototype.dequeue = function () { return this._sendQueue.shift() || this._backgroundQueue.shift(); }; TaskScheduler.prototype.onexecute = function (priority, node, onexecute) { var queue = this.getQueue(priority); queue.delete(node); if (onexecute != undefined) { onexecute(); } }; TaskScheduler.prototype.oncancel = function (priority, node, oncancel, reason) { var queue = this.getQueue(priority); queue.delete(node); if (oncancel != undefined) { oncancel(reason); } }; TaskScheduler.prototype.ondelayexecute = function (handle, onexecute) { clearTimeout(handle); if (onexecute != undefined) { onexecute(); } }; TaskScheduler.prototype.ondelaycancel = function (handle, oncancel, reason) { clearTimeout(handle); if (oncancel != undefined) { oncancel(reason); } }; return TaskScheduler; })(); exports.TaskScheduler = TaskScheduler;