2013-05-11 3 views
0

Я думаю, что у меня трудное время обертывание моей головы вокруг рамки следующего кода:node.js рекурсивного SetTimeout() внутри psuedoclass

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, фактически устанавливая тайм-аут на одну секунду.

Может ли кто-нибудь объяснить мне, что происходит?


EDIT: я смотрел немного больше, и я до сих пор не мог понять проблему охвата, на самом деле.

Что я в итоге делал, следовало за решением, которое было задано для проблемы, которое я пытался решить с помощью 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 не следить за рамки и переменных их родителей ?

ответ

4

Ваша первоначальная проблема заключается в том, что вы были вызоваthis.tick внутри вашего setTimeout:

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

Вместо этого, вы хотите передать ссылку к функции this.tick:

setTimeout(this.tick, this.time); 

Это фиксирует проблему для первого цикла, но второй вызов t o 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(); 
+0

Замечательно, большое вам спасибо. Я пришел к аналогичному выводу после того, как некоторое время с ним связался, и в итоге использовал трюк «сам». Спасибо, что познакомил меня с «bind». Является ли это более правильным, чем полагаться на переменную? –

+0

Я использую 'bind' (и эквивалент CoffeeScript' => '), потому что я думаю, что он выглядит лучше всего в большинстве случаев, но многие люди используют' self'. Стоит отметить, что некоторые старые браузеры не поддерживают 'Function.prototype.bind', поэтому' self' может быть лучше в тех случаях, если вы не используете прокладку. –

+0

Прохладный, спасибо за информацию! –

Смежные вопросы