I made this piece of code to detect inactivity on different aspects of my app. It is part of a set of pieces to analyze user behavior.
Not saying it's ugly, but good looking constructive criticism to help me improve my code and could be useful to me for other similar components.
function InactivityTimeout(idle_time, callback) {
this.state = 0; // 0-new, 1=active, 2=idle
this.idle_time = idle_time;
this.callback = callback;
this.start();
}
InactivityTimeout.prototype.start = function() {
this.state = 1;
this.timer = setTimeout(this.timeout.bind(this), this.idle_time);
}
InactivityTimeout.prototype.activity = function() {
if (this.state == 1) {
clearTimeout(this.timer);
}
this.start();
}
InactivityTimeout.prototype.timeout = function() {
this.state = 2;
this.callback();
}
/// usage
var timer=new InactivityTimeout(5000, function() {
alert("idle reached");
});
var el = document.getElementById('btn');
el.onclick = function() {
timer.activity();
}
<button id="btn">Foo</button>
1 Answer 1
You could pass in an object into the constructor instead of using arguments. That way, you don't have to mind order. Additionally, you could add in defaults:
function InactivityTimer(options){
// Defaults
this.defaults = {
timeout : 10
};
// Merge options to defaults> Let's just say you use jQuery.
this.options = $.extend({}, this.defaults, this.options);
}
Now you wouldn't want to make this code run all the time, so I suggest you add in a start
as well as a stop
. You could also add in an autostart
in options
so it starts as soon as an instance is created.
InactivityTimer.prototype.start = function(){
if(this.timer) return;
this.timer = setTimeout(function(){
...
},this.options.timeout);
}
InactivityTimer.prototype.stop = function(){
clearTimeout(this.timer);
this.timer = null;
}
You wouldn't want to hard-code all the code that runs when activity or inactivity occurs. I suggest you extend from an EventEmitter object. I have a simple implementation of such, which you could just plug in. Now you emit events in your code, and code outside can listen.
function InactivityTimer(options){
EventEmitter.call(this); // Inherit properties
...
}
InactivityTimer.prototype = new EventEmitter();
InactivityTimer.prototype.start = function(){
if(this.timer) return;
this.timer = setTimeout(function(){
this.emit('idle');
},this.options.timeout);
this.emit('start');
}
InactivityTimer.prototype.stop = function(){
clearTimeout(this.timer);
this.timer = null;
this.emit('stop');
}
var idleCheck = new InactivityTimer({...});
idleCheck.on('start',function(){
// timer started
});
idleCheck.on('stop',function(){
// timer stopped
});
idleCheck.on('idle',function(){
// user became idle
});
idleCheck.on('active',function(){
// user became active
});
The same with listening for events instead of hard-coding the code that reacts to the events into InactivityTimer
, you'd might want to also extract the code that listens for activity. Activity can be anything, and the consumer of your code might consider only click
or probably mouse movement etc. Suggesting you add observe
to listen for certain activity.
InactivityTimer.prototype.observe = function(observer){
var instance = this;
// Call the observer, passing it a callback that should be called when an event happens
observer.call(this, function(){
clearTimeout(instance.timer); // clear the timer
instance.emit('active'); // inform listeners that timer became active
instance.start // start another timer
});
});
// Usage
var timer = new InactivityTimer({...});
timer.observe(function(activate){
$('body').on('click',activate); // Observe body clicks
$(window).on('scroll',activate); // Observe scrolling
});
-
\$\begingroup\$ Wow how do you learn all of these. Did you take any inspiration of this implementation from somewhere? \$\endgroup\$JohnnyQ– JohnnyQ2017年09月07日 03:00:53 +00:00Commented Sep 7, 2017 at 3:00
Explore related questions
See similar questions with these tags.