Something went wrong on our end
Select Git revision
Monster.DOM.html
-
Volker Schukai authoredVolker Schukai authored
processing.js 5.04 KiB
'use strict';
/**
* @author schukai GmbH
*/
import {internalSymbol} from "../constants.js";
import {assignToNamespace, Monster} from '../namespace.js';
import {Base} from "../types/base.js";
import {getGlobalFunction} from "../types/global.js";
import {isFunction, isInteger} from "../types/is.js";
import {Queue} from "../types/queue.js";
import {validateFunction, validateInteger} from "../types/validate.js";
/**
* @private
*/
class Callback {
/**
*
* @param {function} callback
* @param {int|undefined} time
* @throws {TypeError} value is not a function
* @throws {TypeError} value is not an integer
* @private
*/
constructor(callback, time) {
this[internalSymbol] = {
callback: validateFunction(callback),
time: validateInteger(time ?? 0)
};
}
/**
* @private
* @param {*} data
* @return {Promise}
*/
run(data) {
const self = this;
return new Promise((resolve, reject) => {
getGlobalFunction('setTimeout')(() => {
try {
resolve(self[internalSymbol].callback(data));
} catch (e) {
reject(e);
}
},
self[internalSymbol].time);
})
}
}
/**
* This class allows to execute several functions in order.
*
* Functions and timeouts can be passed. If a timeout is passed, it applies to all further functions.
* In the example
*
* `timeout1, function1, function2, function3, timeout2, function4`
*
* the timeout1 is valid for the functions 1, 2 and 3 and the timeout2 for the function4.
*
* So the execution time is timeout1+timeout1+timeout1+timeout2
*
* The result of `run()` is a promise.
*
* You can create an instance via the monster namespace `Monster.Util.Processing()`.
*
* ```
* <script type="module">
* import {Monster} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.30.0/dist/monster.js';
* new Monster.Util.Processing()
* </script>
* ```
*
* Alternatively, you can also integrate this class individually.
*
* ```
* <script type="module">
* import {Processing} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.30.0/dist/modules/util/processing.js';
* new Processing();
* </script>
* ```
*
* @example
* import {Processing} from 'https://cdn.jsdelivr.net/npm/@schukai/monster@1.30.0/dist/modules/util/processing.js';
*
* let startTime = +new Date();
*
* new Processing((url)=>{
* return fetch(url)
* },(response)=>{
* // do something with the response
* console.log(response.status, +new Date()-startTime)
* },200,()=>{
* // this function is called 200 seconds after fetch is received.
* console.log('finished', +new Date()-startTime)
* return 'done'
* }).run('https://monsterjs.org/assets/world.json').then(r=>{
* console.log(r)
* // ↦ "done"
* })
*
* @copyright schukai GmbH
* @since 1.21.0
* @memberOf Monster.Util
* @summary Class to be able to execute function chains
*/
class Processing extends Base {
/**
* Create new Processing
*
* Functions and timeouts can be passed. If a timeout is passed, it applies to all further functions.
* In the example
*
* `timeout1, function1, function2, function3, timeout2, function4`
*
* the timeout1 is valid for the functions 1, 2 and 3 and the timeout2 for the function4.
*
* So the execution time is timeout1+timeout1+timeout1+timeout2
*
* @param {int} timeout Timeout
* @param {function} callback Callback
* @throw {TypeError} the arguments must be either integer or functions
*/
constructor() {
super();
this[internalSymbol] = {
queue: new Queue
};
let time = 0
for (const [, arg] of Object.entries(arguments)) {
if (isInteger(arg) && arg >= 0) {
time = arg;
} else if (isFunction(arg)) {
this[internalSymbol].queue.add(new Callback(arg, time))
} else {
throw new TypeError('the arguments must be either integer or functions')
}
}
}
/**
* Adds a function with the desired timeout
* If no timeout is specified, the timeout of the previous function is used.
*
* @param {function} callback
* @param {int|undefined} time
* @throws {TypeError} value is not a function
* @throws {TypeError} value is not an integer
*/
add(callback, time) {
this[internalSymbol].queue.add(new Callback(callback, time))
return this;
}
/**
* Executes the defined functions in order.
*
* @param {*} data
* @return {Promise}
*/
run(data) {
const self = this;
if (this[internalSymbol].queue.isEmpty()) {
return Promise.resolve(data);
}
return this[internalSymbol].queue.poll().run(data).then((result) => {
return self.run(result);
});
}
}
assignToNamespace('Monster.Util', Processing);
export {Monster, Processing}