node.js在伪类中递归setTimeout()

时间:2013-05-11 18:39:33

标签: node.js settimeout

我认为我很难绕过以下代码的范围:

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();

最终发生的事情是,“tick”被调用多次,多次填充堆栈而没有setTimeout实际将超时设置为一秒。

可以向我解释发生了什么事吗?


编辑:我看起来多一点,我仍然无法弄清楚范围问题,真的。

我最终做的是遵循为问题提供的解决方案,我试图通过setTimeout()来解决。

给出的解决方案是:

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"); });

这对我来说更有意义......我现在想知道的是:javascript中的内部函数和对象是不是跟踪其父级的范围和变量?

1 个答案:

答案 0 :(得分:4)

您最初的问题是您在this.tick呼叫 setTimeout

setTimeout(this.tick(), this.time);

相反,您希望将引用传递给this.tick函数:

setTimeout(this.tick, this.time);

这解决了第一个循环的问题,但是对tick的第二次调用(来自setTimeout)没有绑定到正确的范围;因此,您可以使用this将函数引用绑定到bind的当前值:

setTimeout(this.tick.bind(this), this.time);

(如果您愿意,也可以使用self技巧。)

所以,完整的工作计划是:

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();