From 4fd9b8f2b5a98bfcde57970b48fed2488a80f356 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Fri, 17 Sep 2021 21:53:37 +0300 Subject: add in master snapshot of epubjs --- lib/epub.js/src/utils/queue.js | 246 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 lib/epub.js/src/utils/queue.js (limited to 'lib/epub.js/src/utils/queue.js') diff --git a/lib/epub.js/src/utils/queue.js b/lib/epub.js/src/utils/queue.js new file mode 100644 index 0000000..1f8a18a --- /dev/null +++ b/lib/epub.js/src/utils/queue.js @@ -0,0 +1,246 @@ +import {defer, requestAnimationFrame} from "./core"; + +/** + * Queue for handling tasks one at a time + * @class + * @param {scope} context what this will resolve to in the tasks + */ +class Queue { + constructor(context){ + this._q = []; + this.context = context; + this.tick = requestAnimationFrame; + this.running = false; + this.paused = false; + } + + /** + * Add an item to the queue + * @return {Promise} + */ + enqueue() { + var deferred, promise; + var queued; + var task = [].shift.call(arguments); + var args = arguments; + + // Handle single args without context + // if(args && !Array.isArray(args)) { + // args = [args]; + // } + if(!task) { + throw new Error("No Task Provided"); + } + + if(typeof task === "function"){ + + deferred = new defer(); + promise = deferred.promise; + + queued = { + "task" : task, + "args" : args, + //"context" : context, + "deferred" : deferred, + "promise" : promise + }; + + } else { + // Task is a promise + queued = { + "promise" : task + }; + + } + + this._q.push(queued); + + // Wait to start queue flush + if (this.paused == false && !this.running) { + // setTimeout(this.flush.bind(this), 0); + // this.tick.call(window, this.run.bind(this)); + this.run(); + } + + return queued.promise; + } + + /** + * Run one item + * @return {Promise} + */ + dequeue(){ + var inwait, task, result; + + if(this._q.length && !this.paused) { + inwait = this._q.shift(); + task = inwait.task; + if(task){ + // console.log(task) + + result = task.apply(this.context, inwait.args); + + if(result && typeof result["then"] === "function") { + // Task is a function that returns a promise + return result.then(function(){ + inwait.deferred.resolve.apply(this.context, arguments); + }.bind(this), function() { + inwait.deferred.reject.apply(this.context, arguments); + }.bind(this)); + } else { + // Task resolves immediately + inwait.deferred.resolve.apply(this.context, result); + return inwait.promise; + } + + + + } else if(inwait.promise) { + // Task is a promise + return inwait.promise; + } + + } else { + inwait = new defer(); + inwait.deferred.resolve(); + return inwait.promise; + } + + } + + // Run All Immediately + dump(){ + while(this._q.length) { + this.dequeue(); + } + } + + /** + * Run all tasks sequentially, at convince + * @return {Promise} + */ + run(){ + + if(!this.running){ + this.running = true; + this.defered = new defer(); + } + + this.tick.call(window, () => { + + if(this._q.length) { + + this.dequeue() + .then(function(){ + this.run(); + }.bind(this)); + + } else { + this.defered.resolve(); + this.running = undefined; + } + + }); + + // Unpause + if(this.paused == true) { + this.paused = false; + } + + return this.defered.promise; + } + + /** + * Flush all, as quickly as possible + * @return {Promise} + */ + flush(){ + + if(this.running){ + return this.running; + } + + if(this._q.length) { + this.running = this.dequeue() + .then(function(){ + this.running = undefined; + return this.flush(); + }.bind(this)); + + return this.running; + } + + } + + /** + * Clear all items in wait + */ + clear(){ + this._q = []; + } + + /** + * Get the number of tasks in the queue + * @return {number} tasks + */ + length(){ + return this._q.length; + } + + /** + * Pause a running queue + */ + pause(){ + this.paused = true; + } + + /** + * End the queue + */ + stop(){ + this._q = []; + this.running = false; + this.paused = true; + } +} + + +/** + * Create a new task from a callback + * @class + * @private + * @param {function} task + * @param {array} args + * @param {scope} context + * @return {function} task + */ +class Task { + constructor(task, args, context){ + + return function(){ + var toApply = arguments || []; + + return new Promise( (resolve, reject) => { + var callback = function(value, err){ + if (!value && err) { + reject(err); + } else { + resolve(value); + } + }; + // Add the callback to the arguments list + toApply.push(callback); + + // Apply all arguments to the functions + task.apply(context || this, toApply); + + }); + + }; + + } +} + + +export default Queue; +export { Task }; -- cgit v1.2.3