Skip to content

Instantly share code, notes, and snippets.

@loveqoo
Last active February 25, 2017 01:42
Show Gist options
  • Save loveqoo/d903cec8fee60b129091917ee5a068f1 to your computer and use it in GitHub Desktop.
Save loveqoo/d903cec8fee60b129091917ee5a068f1 to your computer and use it in GitHub Desktop.
Javascript Timer
/*
var t = timer.getTimer(1000); // 1 sec
var key1 = t.add(function (){
console.log('1 sec');
});
var key2 = t.add(function (){
console.log('2 sec');
}, 2); // 1 sec, 2 times -> 2 sec
timer.stop(); // all timers is stopped.
timer.status();
All timers is stopped.
------------------------------
timer(1000ms delay, 2 task(s))
timer.start(); // all timers is running.
t.cancel(key1);
timer.status();
All timers is running.
------------------------------
timer(1000ms delay, 1 task(s))
t.add(function () {
console.log('run once. good bye.');
return false;
});
*/
(function (root, moduleName, factory) {
if (typeof define === 'function' && define.amd) {
define([moduleName], factory);
} else {
root[moduleName] = factory();
}
}(this, 'timer', function () {
var timer = (function (delay, autoStart) {
var timerId, subTimers = [],
error = function (msg) { throw new Error(msg);},
resourceToggler = function (odd, even){
var flag = true,
getOdd = function () { return flag ? odd : even; },
getEven = function () { return flag ? even : odd; },
toggle = function () { flag = !flag; };
return { getOdd:getOdd, getEven:getEven, toggle: toggle };
},
rangeRepeater = function (start, end, callback) {
(start >= end) && error('invalid parameters: ' + start + ' >= ' + end);
var current = start,
update = function () {
if (current + 1 <= end) { current += 1;} else { current = start;}
};
return {
get: function () {
var result = current;
(typeof callback === 'function') && callback(result);
update();
return result;
},
reset: function () {
current = start;
}
};
}, subTimersCache = {},
start = function () {
if (timerId) { return; }
(function runNext() {
for (var i = 0; i < subTimers.length; i++ ) {
if (subTimers[i]() === false) { subTimers.splice(i, 1);}
}
timerId = setTimeout(runNext, delay);
})();
},
stop = function () {
if (!timerId) { return; }
clearTimeout(timerId);
timerId = 0;
},
getTimer = function (subDelay) {
if (subTimersCache[subDelay]) { return subTimersCache[subDelay]; }
(delay > subDelay || subDelay % delay !== 0) && error('invalid delay');
var repeat = subDelay / delay, waitSet = resourceToggler([],[]),
subTimer = (function () {
var subscribers = [],
add = function (f, times) {
if (times > 1) {
var repeater = rangeRepeater(1, times);
return subscribers.push(function () {
if (repeater.get() === times) { return f(); }
}) - 1;
}
return subscribers.push(f) - 1;
},
cancel = function (seq) {
waitSet.getOdd().push(seq);
},
publish = function () {
waitSet.toggle();
var cancelList = waitSet.getEven();
for (var j = 0; j < cancelList.length; j++) {
subscribers.splice(cancelList[j], 1);
cancelList.splice(j, 1);
}
for (var i = 0; i < subscribers.length; i++) {
if (subscribers[i]() === false) { subscribers.splice(i, 1);}
}
},
status = function () {
return 'timer(' + subDelay + 'ms delay, ' + subscribers.length + ' task(s))';
};
return { add: add, cancel: cancel, publish: publish, status: status };
})(); // subTimer
if (repeat > 1) {
var repeater = rangeRepeater(1, repeat);
subTimers.push(function () {
if (repeater.get() === repeat) { return subTimer.publish(); }
});
} else {
subTimers.push(function () {
subTimer.publish();
});
}
var subTimerWrapped = {
add: function () {
return subTimer.add.apply(subTimer, arguments);
},
cancel: function () {
subTimer.cancel.apply(subTimer, arguments);
},
status: function () {
return subTimer.status.apply(subTimer, arguments);
}
}
subTimersCache[subDelay] = subTimerWrapped;
return subTimerWrapped;
}, // getTimer
status = function (out) {
var messages = [];
messages.push('All timers is ' + (timerId ? 'running.' : 'stopped.'));
messages.push('------------------------------');
for (var key in subTimersCache) {
if (!subTimersCache.hasOwnProperty(key)) { continue; }
messages.push(subTimersCache[key].status());
}
(out || console.log)(messages.join('\r\n'));
};
autoStart && start();
return { start: start, stop: stop, getTimer: getTimer, status: status };
})(this.timerDefaultDelay || 100, this.timerAutoStart || false); // timer
return timer;
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment