I have a problem with a javascript-Function, where I can't use callback-Functions.
The function gets a List of "commands", and iterates over them. It performs one command after another. In order to do that, I have to use a recursive Function with callbacks.
Here's an example to describe it:
function processList( inputArray, cb ){
if(inputArray.length == 0) return cb(); //No commands left
var command = inputArray.pop(); //Get last Element from the List
processCommand(command, function(){ //Execute the command
return processList(inputArray, cb); //Continue with the next command, when this one finished
});
}
function processCommand(command, cb){
setTimeout(function(){
console.log("Processed command "+command);
cb();
}, 10);
}
This is how I call the function:
processList( ["cmd1", "cmd2", "cmd3"], function(){
console.log("DONE");
});
It works perfectly, one command is executed after the previous one.
My Problem:
The list contains thousands of Elements, and it's even possible that the list gets new commands during processing. And I reach the maximum call-stack within seconds.
I don't need the call-stack. When I finished the last command, there are just thousands of returns, which guide me back to the function, which started everything.
I have no idea how to solve this problem, and I don't want to use busy waiting (which makes the code extremly inefficient).
Is there another trick? Like signals or trashing the call-stack?
Edit:
Here's a jsFiddle for demonstration: http://jsfiddle.net/db6J8/ (Notice, that your browser-tab might freeze/crash)
The error-Message is Uncaught RangeError: Maximum call stack size exceeded
I tested it with Chrome, you might have to increase the Array in other Browsers (IE has a huge Callstack).
Edit2:
Thanks for you help, I didn't recognise the difference between adding/removing the timeout. Hover, it doesn't solve my Problem. Here are some more details: I have different commands. Some commands are synchronous, others are asynchronous. So I have to use callback-Functions, but still have the problem with the callstack.
Here's an updated example:
var commands = [];
for(var i=15000; i>=0;i--){ commands.push(i); }
processList(commands, function(){
alert("DONE");
});
function processList( inputArray, cb ){
if(inputArray.length == 0) return cb(); //No commands left
var command = inputArray.pop(); //Get last Element from the List
processCommand(command, function(){ //Execute the command
return processList(inputArray, cb); //Continue with the next command, when this one finished
});
}
function processCommand(command, cb){
if(command%2 == 0){ //This command is synchron
console.log("Processed sync. command "+command);
cb();
}else{
setTimeout(function(){
console.log("Processed async. command "+command);
cb();
}, 1);
}
}
And the fiddle: http://jsfiddle.net/B7APC/