Reputation: 459
I'm trying to emit events inside of loop. But, just launch the first event(start) and once.
The behavior in console must be: a emit event start emit event finish b emit event start emit event finish
another again
a emit event start emit event finish b emit event start emit event finish
However, it's behave the next way:
a emit event start b
another again
a b
Why the event only is emit once?
var server = require('http').createServer();
var io = require('socket.io')(server);
var sleep = require('sleep');
io.on('connection', function(socket){
socket.on('disconnect', function(){});
});
server.listen(3000);
function B() {
this.bundles = ['a', 'b'];
this.currentPosition = 0;
this.run = function() {
var bundle = this.bundles[this.currentPosition];
console.log(bundle);
io.emit('start', { 'bundle': bundle });
io.emit('finish', { 'bundle': bundle });
++this.currentPosition;
if (this.bundles[this.currentPosition] === undefined) {
this.currentPosition = 0;
}
sleep.sleep(2);
this.run();
}
}
//wait to start server
setTimeout(function(){
var b = new B();
b.run();
}, 6000);
Upvotes: 1
Views: 2887
Reputation: 59213
Try changing it to a setInterval
.
http://codepen.io/Chevex/pen/zGdQXQ
this.run = function() {
var bundle = this.bundles[this.currentPosition];
console.log(bundle);
io.emit('start', { 'bundle': bundle });
io.emit('finish', { 'bundle': bundle });
++this.currentPosition;
if (this.bundles[this.currentPosition] === undefined) {
this.currentPosition = 0;
}
}
setInterval(this.run.bind(this), 2000);
The interval will run every 2 seconds and won't flood your call stack.
Whenever you call a function from another function, you build a call stack.
function foo() {
bar();
}
function bar() {
console.log('end of stack, returning');
}
foo();
The above code would build a stack like this:
-> event loop
-> foo
-> bar
-> console.log
Then as the functions start returning, they pop off the stack one by one. What this means is that when you call a function from within itself, you will definitely exhaust the call stack if the recursive calls never stop.
function foo() {
foo();
}
foo();
This would result in an ugly call stack that will run your memory dry.
-> event loop
-> foo
-> foo
-> foo
-> foo
-> foo
-> etc...
You can see that the JavaScript engine even tries to detect when this is happening and throw an exception. The engine doesn't always catch these though if the recursive stack is more complicated. It's best to just avoid it and stick to setInterval
.
By using setInterval
you're registering a function with node and telling it to fire it each time a certain number of milliseconds has passed. This saves your call stack because the function is fired, returns, and then starts again when the node event loop detects that n
milliseconds has passed again. No infinite call stack that would result in a...
...Stack Overflow
PS - Now you understand this site's own logo. It's a call stack :)
Upvotes: 5