mirror of
https://github.com/futurepress/epub.js.git
synced 2025-10-03 14:59:18 +02:00

* Initial embedding support * Updates for rendering in embedded webviews * toLowerCase nodeName check
246 lines
4 KiB
JavaScript
246 lines
4 KiB
JavaScript
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 {int} 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 };
|