scheduling
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -1,1 +0,1 @@ | ||
!function(root,factory){"object"==typeof exports&&"object"==typeof module?module.exports=factory():"function"==typeof define&&define.amd?define("scheduler",[],factory):"object"==typeof exports?exports.scheduler=factory():root.scheduler=factory()}(this,function(){return function(modules){function __webpack_require__(moduleId){if(installedModules[moduleId])return installedModules[moduleId].exports;var module=installedModules[moduleId]={i:moduleId,l:!1,exports:{}};return modules[moduleId].call(module.exports,module,module.exports,__webpack_require__),module.l=!0,module.exports}var installedModules={};return __webpack_require__.m=modules,__webpack_require__.c=installedModules,__webpack_require__.d=function(exports,name,getter){__webpack_require__.o(exports,name)||Object.defineProperty(exports,name,{configurable:!1,enumerable:!0,get:getter})},__webpack_require__.n=function(module){var getter=module&&module.__esModule?function(){return module.default}:function(){return module};return __webpack_require__.d(getter,"a",getter),getter},__webpack_require__.o=function(object,property){return Object.prototype.hasOwnProperty.call(object,property)},__webpack_require__.p="",__webpack_require__(__webpack_require__.s=0)}([function(module,exports,__webpack_require__){"use strict";function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||!1,descriptor.configurable=!0,"value"in descriptor&&(descriptor.writable=!0),Object.defineProperty(target,descriptor.key,descriptor)}}return function(Constructor,protoProps,staticProps){return protoProps&&defineProperties(Constructor.prototype,protoProps),staticProps&&defineProperties(Constructor,staticProps),Constructor}}(),Scheduler=function(){function Scheduler(){_classCallCheck(this,Scheduler),this._delayTasks=[],this._nextTasks=[],this._deferTasks=[],this._highTasks=[],this._usurpTask=[],this._enterframeTasks=[],this._idTable=0,this._startTime=(new Date).getTime(),this._deltaTime=0,this._internalTime=0,this._isPaused=!1,this._loop()}return _createClass(Scheduler,[{key:"addEF",value:function(func,params){params=params||[];var id=this._idTable;return this._enterframeTasks[id]={func:func,params:params},this._idTable++,id}},{key:"removeEF",value:function(id){return void 0!==this._enterframeTasks[id]&&(this._enterframeTasks[id]=null),-1}},{key:"delay",value:function(func,params,_delay){var time=(new Date).getTime(),t={func:func,params:params,delay:_delay,time:time};this._delayTasks.push(t)}},{key:"defer",value:function(func,params){var t={func:func,params:params};this._deferTasks.push(t)}},{key:"next",value:function(func,params){var t={func:func,params:params};this._nextTasks.push(t)}},{key:"usurp",value:function(func,params){var t={func:func,params:params};this._usurpTask.push(t)}},{key:"pause",value:function(){this._isPaused=!0}},{key:"advance",value:function(){this._internalTime+=1/60}},{key:"resume",value:function(){this._isPaused=!1}},{key:"_process",value:function(){var i=0,task=void 0,interval=void 0;for(i=0;i<this._enterframeTasks.length;i++)null!==(task=this._enterframeTasks[i])&&void 0!==task&&task.func(task.params);for(;this._highTasks.length>0;)task=this._highTasks.pop(),task.func(task.params);var startTime=(new Date).getTime(),_startTime=this._deltaTime;for(this._deltaTime=(startTime-this._startTime)/1e3,i=0;i<this._delayTasks.length;i++)task=this._delayTasks[i],startTime-task.time>task.delay&&(task.func(task.params),this._delayTasks.splice(i,1));for(startTime=(new Date).getTime(),this._deltaTime=(startTime-this._startTime)/1e3,interval=1e3/60;this._deferTasks.length>0;){if(task=this._deferTasks.shift(),!((new Date).getTime()-startTime<interval)){this._deferTasks.unshift(task);break}task.func(task.params)}for(startTime=(new Date).getTime(),this._deltaTime=(startTime-this._startTime)/1e3,interval=1e3/60;this._usurpTask.length>0;)task=this._usurpTask.shift(),(new Date).getTime()-startTime<interval&&task.func(task.params);this._highTasks=this._highTasks.concat(this._nextTasks),this._nextTasks=[],this._usurpTask=[],this._isPaused||(this._internalTime+=this._deltaTime-_startTime)}},{key:"_loop",value:function(){var _this=this;this._process(),window.requestAnimationFrame(function(){return _this._loop()})}},{key:"intervalTime",get:function(){return this._internalTime}},{key:"deltaTime",get:function(){return this._deltaTime}}]),Scheduler}(),scheduler=new Scheduler;exports.default=scheduler}])}); | ||
let n=window,e=60,o=performance.now(),r=0,t=0,a=o;const f=[],u=[],c=[],s=[];let i=[],l=[],g=0;!function g(){!function(){let n,g=0,m=1e3/e,p=0;for(g=0;g<f.length;g++)n=f[g],null!=n&&n.func(n.args);for(;i.length>0;)n=i.pop(),n.func(n.args);let h=performance.now();for(t=(h-o)/1e3,r=h-a,g=0;g<u.length;g++)n=u[g],h-n.time>n.delay&&(n.func(n.args),u.splice(g,1));for(h=performance.now();c.length>0;){if(n=c.shift(),p=performance.now(),console.log("Defer :",p,h,n.args.name,n.args.target),!(p-h<m)){console.log("not enough time, push to next frame",n.args.name),c.unshift(n);break}n.func(n.args)}for(h=performance.now();s.length>0;)n=s.shift(),p=performance.now(),p-h<m&&n.func(n.args);a=h,i=i.concat(l),l=[]}(),n.requestAnimationFrame(g)}();var m={addEF:function(n,e){const o=++g;return console.log("add task",o),f[o]={func:n,args:e},o},removeEF:function(n){return void 0!==f[n]&&(f[n]=null),-1},delay:function(n,e,o){const r=performance.now();u.push({func:n,args:e,delay:o,time:r})},next:function(n,e){l.push({func:n,args:e})},defer:function(n,e){c.push({func:n,args:e})},usurp:function(n,e){s.push({func:n,args:e})},setRequestAnimationFrameSource:function(e){n=e},setFrameRate:function(n){e=n},getElapsedTime:function(){return t},getDeltaTime:function(){return r}};export default m; |
// main.js | ||
// import Scheduler from '../src/scheduler'; | ||
import Scheduler from '../build/scheduler'; | ||
// import Scheduler from "../src/scheduler"; | ||
import Scheduler from "../build/scheduler"; | ||
let index = Scheduler.addEF(loop); | ||
let count = 0; | ||
let efIndex; | ||
function loop() { | ||
console.log('Loop', count, Scheduler.deltaTime, Scheduler.intervalTime); | ||
count ++; | ||
if(count > 20) { | ||
Scheduler.removeEF(index); | ||
Scheduler.next(call, '00'); | ||
} else if(count > 10) { | ||
Scheduler.pause(); | ||
} | ||
function logMessage(msg) { | ||
console.log(msg, Scheduler.getDeltaTime(), Scheduler.getElapsedTime()); | ||
} | ||
Scheduler.delay(call, '01', 500); | ||
Scheduler.delay(call, '02', 1000); | ||
function log(msg) { | ||
logMessage(msg ? msg : "-"); | ||
if (count++ > 60) { | ||
Scheduler.removeEF(efIndex); | ||
} | ||
} | ||
efIndex = Scheduler.addEF(log); | ||
Scheduler.delay(log, "Delayed task - ", 2000); | ||
function call(str) { | ||
console.log('Calling : ', str); | ||
function deferTest(o) { | ||
let t = 0; | ||
while (t < o.target) { | ||
t += Math.random(); | ||
} | ||
} | ||
window.addEventListener('keydown', (e) => { | ||
if(e.keyCode === 32) { | ||
Scheduler.advance(); | ||
console.log(Scheduler.intervalTime); | ||
} | ||
}) | ||
for (let i = 0; i < 10; i++) { | ||
const t = 600000; | ||
const target = Math.floor(t + Math.random() * t); | ||
Scheduler.defer(deferTest, { name: "task" + i, target }); | ||
} |
{ | ||
"name": "scheduling", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "A enterframe tool", | ||
"main": "build/scheduler.js", | ||
"module": "src/scheduler.js", | ||
"module": "build/scheduler.js", | ||
"browser": "build/scheduler.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"lint": "eslint src", | ||
"lint:fix": "eslint --fix src", | ||
"start": "npm run dev", | ||
"dev": "NODE_ENV=development webpack-dev-server --open", | ||
"build": "NODE_ENV=production webpack --progress --colors" | ||
"build": "rollup -c" | ||
}, | ||
@@ -34,4 +32,8 @@ "repository": { | ||
"webpack": "^3.6.0", | ||
"webpack-dev-server": "^2.8.2" | ||
"webpack-dev-server": "^2.8.2", | ||
"rollup": "^2.39.0", | ||
"@rollup/plugin-commonjs": "^11.0.1", | ||
"@rollup/plugin-node-resolve": "^7.0.0", | ||
"rollup-plugin-terser": "^7.0.2" | ||
} | ||
} |
@@ -1,163 +0,235 @@ | ||
// Scheduler.js | ||
const FRAMERATE = 60; | ||
// animation frame source | ||
let afSource = window; | ||
class Scheduler { | ||
// expected frame rate, for defer / usurp tasks | ||
let frameRate = 60; | ||
constructor() { | ||
this._delayTasks = []; | ||
this._nextTasks = []; | ||
this._deferTasks = []; | ||
this._highTasks = []; | ||
this._usurpTask = []; | ||
this._enterframeTasks = []; | ||
this._idTable = 0; | ||
// time | ||
let startTime = performance.now(); | ||
let deltaTime = 0; | ||
let elapsedTime = 0; | ||
let prevTime = startTime; | ||
this._startTime = new Date().getTime(); | ||
// tasks | ||
const enterframeTasks = []; | ||
const delayTasks = []; | ||
const deferTasks = []; | ||
const usurpTasks = []; | ||
let highTasks = []; | ||
let nextTasks = []; | ||
this._deltaTime = 0; | ||
this._internalTime = 0; | ||
this._isPaused = false; | ||
// indexing | ||
let idTable = 0; | ||
/** | ||
* Add an enterframe task | ||
* | ||
* @param {function} mFunc the function to be called in enterframe | ||
* @param {object} mArgs the arguments for the function | ||
* @returns {number} the id of the task | ||
*/ | ||
function addEF(mFunc, mArgs) { | ||
const id = ++idTable; | ||
this._loop(); | ||
} | ||
console.log("add task", id); | ||
enterframeTasks[id] = { func: mFunc, args: mArgs }; | ||
return id; | ||
} | ||
/** | ||
* Remove an enterframe task | ||
* | ||
* @param {number} mIndex the id of the task to be removed | ||
* @returns {number} return -1 | ||
*/ | ||
function removeEF(mIndex) { | ||
if (enterframeTasks[mIndex] !== undefined) { | ||
enterframeTasks[mIndex] = null; | ||
} | ||
return -1; | ||
} | ||
// PUBLIC METHODS | ||
/** | ||
* Add a delayed task | ||
* | ||
* @param {function} mFunc the function to be called | ||
* @param {object} mArgs the arguments for the function | ||
* @param {number} mDelay the delay time for the task | ||
* @returns {number} the id of the task | ||
*/ | ||
function delay(mFunc, mArgs, mDelay) { | ||
const time = performance.now(); | ||
delayTasks.push({ func: mFunc, args: mArgs, delay: mDelay, time }); | ||
} | ||
addEF(func, params) { | ||
params = params || []; | ||
const id = this._idTable; | ||
this._enterframeTasks[id] = { func, params }; | ||
this._idTable ++; | ||
return id; | ||
} | ||
/** | ||
* Add a task for next frame | ||
* | ||
* @param {function} mFunc the function to be called | ||
* @param {object} mArgs the arguments for the function | ||
* @returns {number} the id of the task | ||
*/ | ||
function next(mFunc, mArgs) { | ||
nextTasks.push({ func: mFunc, args: mArgs }); | ||
} | ||
removeEF(id) { | ||
if (this._enterframeTasks[id] !== undefined) { | ||
this._enterframeTasks[id] = null; | ||
} | ||
return -1; | ||
} | ||
/** | ||
* Add a deffered task that only execute when there's enough time left in the frame. | ||
* Otherwise try again in the next frame ( Green threading ) | ||
* | ||
* @param {function} mFunc the function to be called | ||
* @param {object} mArgs the arguments for the function | ||
* @returns {number} the id of the task | ||
*/ | ||
function defer(mFunc, mArgs) { | ||
deferTasks.push({ func: mFunc, args: mArgs }); | ||
} | ||
delay(func, params, delay) { | ||
const time = new Date().getTime(); | ||
const t = { func, params, delay, time }; | ||
this._delayTasks.push(t); | ||
} | ||
/** | ||
* Add an usurp task, that only execute when there's enough time left in the frame, otherwise abandoned. | ||
* | ||
* @param {function} mFunc the function to be called | ||
* @param {object} mArgs the arguments for the function | ||
* @returns {number} the id of the task | ||
*/ | ||
function usurp(mFunc, mArgs) { | ||
usurpTasks.push({ func: mFunc, args: mArgs }); | ||
} | ||
defer(func, params) { | ||
const t = { func, params }; | ||
this._deferTasks.push(t); | ||
} | ||
/** | ||
* Get the delta time from last frame | ||
* | ||
* @returns {number} the elapsed time from the last frame | ||
*/ | ||
function getDeltaTime() { | ||
return deltaTime; | ||
} | ||
next(func, params) { | ||
const t = { func, params }; | ||
this._nextTasks.push(t); | ||
} | ||
/** | ||
* Get the elapsed time from the app starts | ||
* | ||
* @returns {number} the elapsed tiem of the app ( in sec ) | ||
*/ | ||
function getElapsedTime() { | ||
return elapsedTime; | ||
} | ||
usurp(func, params) { | ||
const t = { func, params }; | ||
this._usurpTask.push(t); | ||
} | ||
/** | ||
* Set the animation source of the scheduler | ||
* | ||
* @param {object} mSource the source of animation frame, e.g. window or XR | ||
*/ | ||
function setRequestAnimationFrameSource(mSource) { | ||
afSource = mSource; | ||
} | ||
/** | ||
* Set the (expected) frame rate for defer / usurp tasks | ||
* | ||
* @param {number} mFrameRate the frame rate | ||
*/ | ||
function setFrameRate(mFrameRate) { | ||
frameRate = mFrameRate; | ||
} | ||
pause() { | ||
this._isPaused = true; | ||
} | ||
/** | ||
* Process all scheduled tasks | ||
*/ | ||
function process() { | ||
let i = 0; | ||
let task; | ||
let interval = 1000 / frameRate; | ||
let current = 0; | ||
// enterframe tasks | ||
for (i = 0; i < enterframeTasks.length; i++) { | ||
task = enterframeTasks[i]; | ||
if (task !== null && task !== undefined) { | ||
task.func(task.args); | ||
} | ||
} | ||
advance() { | ||
this._internalTime += 1 / FRAMERATE; | ||
} | ||
// high priority tasks | ||
while (highTasks.length > 0) { | ||
task = highTasks.pop(); | ||
task.func(task.args); | ||
} | ||
// get current time | ||
let currentTime = performance.now(); | ||
elapsedTime = (currentTime - startTime) / 1000; | ||
deltaTime = currentTime - prevTime; | ||
resume() { | ||
this._isPaused = false; | ||
} | ||
// delay tasks | ||
for (i = 0; i < delayTasks.length; i++) { | ||
task = delayTasks[i]; | ||
if (currentTime - task.time > task.delay) { | ||
task.func(task.args); | ||
delayTasks.splice(i, 1); | ||
} | ||
} | ||
// PRIVATE METHODS | ||
// defer tasks | ||
currentTime = performance.now(); | ||
while (deferTasks.length > 0) { | ||
task = deferTasks.shift(); | ||
current = performance.now(); | ||
console.log( | ||
"Defer :", | ||
current, | ||
currentTime, | ||
task.args.name, | ||
task.args.target | ||
); | ||
if (current - currentTime < interval) { | ||
task.func(task.args); | ||
} else { | ||
console.log("not enough time, push to next frame", task.args.name); | ||
deferTasks.unshift(task); | ||
break; | ||
} | ||
} | ||
_process() { | ||
let i = 0; | ||
let task; | ||
let interval; | ||
let current; | ||
for (i = 0; i < this._enterframeTasks.length; i++) { | ||
task = this._enterframeTasks[i]; | ||
if (task !== null && task !== undefined) { | ||
task.func(task.params); | ||
} | ||
} | ||
// usurp tasks | ||
currentTime = performance.now(); | ||
while (usurpTasks.length > 0) { | ||
task = usurpTasks.shift(); | ||
current = performance.now(); | ||
if (current - currentTime < interval) { | ||
task.func(task.args); | ||
} | ||
// else do nothing, tasks abandoned | ||
} | ||
while (this._highTasks.length > 0) { | ||
task = this._highTasks.pop(); | ||
task.func(task.params); | ||
} | ||
// save time | ||
prevTime = currentTime; | ||
// clear tasks | ||
highTasks = highTasks.concat(nextTasks); | ||
nextTasks = []; | ||
} | ||
let startTime = new Date().getTime(); | ||
let _startTime = this._deltaTime; | ||
this._deltaTime = (startTime - this._startTime)/1000; | ||
for (i = 0; i < this._delayTasks.length; i++) { | ||
task = this._delayTasks[i]; | ||
if (startTime - task.time > task.delay) { | ||
task.func(task.params); | ||
this._delayTasks.splice(i, 1); | ||
} | ||
} | ||
startTime = new Date().getTime(); | ||
this._deltaTime = (startTime - this._startTime)/1000; | ||
interval = 1000 / FRAMERATE; | ||
while (this._deferTasks.length > 0) { | ||
task = this._deferTasks.shift(); | ||
current = new Date().getTime(); | ||
if (current - startTime < interval) { | ||
task.func(task.params); | ||
} else { | ||
this._deferTasks.unshift(task); | ||
break; | ||
} | ||
} | ||
startTime = new Date().getTime(); | ||
this._deltaTime = (startTime - this._startTime)/1000; | ||
interval = 1000 / FRAMERATE; | ||
while (this._usurpTask.length > 0) { | ||
task = this._usurpTask.shift(); | ||
current = new Date().getTime(); | ||
if (current - startTime < interval) { | ||
task.func(task.params); | ||
} | ||
} | ||
this._highTasks = this._highTasks.concat(this._nextTasks); | ||
this._nextTasks = []; | ||
this._usurpTask = []; | ||
if(!this._isPaused) { | ||
this._internalTime += this._deltaTime - _startTime; | ||
} | ||
} | ||
_loop() { | ||
this._process(); | ||
window.requestAnimationFrame(() => this._loop()); | ||
} | ||
get intervalTime() { | ||
return this._internalTime; | ||
} | ||
get deltaTime() { | ||
return this._deltaTime; | ||
} | ||
/** | ||
* Looping | ||
*/ | ||
function loop() { | ||
process(); | ||
afSource.requestAnimationFrame(loop); | ||
} | ||
const scheduler = new Scheduler(); | ||
// start the engine | ||
loop(); | ||
export default scheduler; | ||
// exports | ||
export default { | ||
addEF, | ||
removeEF, | ||
delay, | ||
next, | ||
defer, | ||
usurp, | ||
setRequestAnimationFrameSource, | ||
setFrameRate, | ||
getElapsedTime, | ||
getDeltaTime, | ||
}; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
332
0
11900
9
10
2
1