summaryrefslogtreecommitdiff
path: root/lib/epub.js/src/utils/queue.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/epub.js/src/utils/queue.js')
-rw-r--r--lib/epub.js/src/utils/queue.js246
1 files changed, 246 insertions, 0 deletions
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 };