I think I'm having a difficult time wrapping my head around the scope of the following code:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick(), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();
What ends up happening, is that the "tick" gets called many, many times filling up the stack without the setTimeout actually setting the timeout to one second.
Could any explain to me what's going on?
EDIT: I looked a little bit more, and I still couldn't figure out the issue of scope, really.
What I ended up doing was following the solution that was given for the problem, which I tried to solve by way of setTimeout().
The solution given was:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
var self = this;
this.time = time;
setInterval(function() {
self.emit('tick');
}, self.time);
};
util.inherits(Ticker, EventEmitter);
var ticker = new Ticker(1000);
ticker.on('tick', function() { console.log("TICK"); });
It does make more sense to me... What I'm wondering now is: Do inner functions and objects in javascript not keep track of their parent's scope and variables?
Your initial problem is that you were calling this.tick inside your setTimeout:
setTimeout(this.tick(), this.time);
Instead, you want to pass a reference to the this.tick function:
setTimeout(this.tick, this.time);
This fixes the problem for the first loop, but the second call to tick (which comes from the setTimeout) is not bound to the correct scope; so, you can bind the function reference to the current value of this using bind:
setTimeout(this.tick.bind(this), this.time);
(You can also use the self trick if you prefer.)
So, the full working program is:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick.bind(this), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();