I'm not so experienced in async javascript. How can I call the commands without hardcoding the amount of commands or using eval?
var commands = [
// command 1: result: 0, stdout: ""
function (stdin, callback) {
callback(0, "");
},
// command 2: result: 1, stdout: ""
function (stdin, callback) {
callback(1, "");
},
// command 3: result: 0, stdout: ""
function (stdin, callback) {
callback(0, "");
},
// ...
];
var stdin = "foo";
var end = function (result, stdout) {
console.log(result);
console.log(stdout);
};
commands[0](stdin, function (result, stdout) {
commands[1](stdout, function (result, stdout) {
commands[2](stdout, end);
});
});
-
Just because it's callbacks, it doesn't mean its asynchronous, so I'm having a hard time figuring out why you really need this. You should clarify why you need this, I'm tempted to vote to close even though I voted it up initially... Is this purely a hypothetical?Ruan Mendes– Ruan Mendes2012年11月08日 16:48:13 +00:00Commented Nov 8, 2012 at 16:48
-
It looks like you want some sort of queuing behavior.zzzzBov– zzzzBov2012年11月08日 16:49:53 +00:00Commented Nov 8, 2012 at 16:49
-
By the way, the code doesn't do anything that I can make sense of... jsfiddle.net/eJS3mRuan Mendes– Ruan Mendes2012年11月08日 17:01:19 +00:00Commented Nov 8, 2012 at 17:01
2 Answers 2
Final answer:
I'm using recursion to go through the commands array. You pass the loop function an array of commands and the last callback to be called (you can also pass as a fourth optional parameter the index of the array in which you wish to start the loop - defaults to zero).
var commands = [
// echo foo
function (stdin, callback) {
callback(0, "foo");
},
// touppercase
function (stdin, callback) {
callback(1, stdin.toUpperCase());
}
];
var stdin = "",
loop = function(commands, lastCallback, stdin, startIndex) {
(function insideLoop(i, stdout) {
commands[i](stdout, (i + 1 < commands.length) ? function(result, stdout){ insideLoop(i + 1, stdout); } : lastCallback);
})(startIndex || 0, stdin);
},
end = function (result, stdout) {
console.log(stdout);
};
loop(commands, end, stdin);
4 Comments
result, stdout parameters to the anonymous function. It works now, you can see the live code example. One last thing, I can seem to understand result purpose.To let those functions run asyncronously, you need a way to invoke them by making sure that inbetween the calls, a browser (or actually any implementation) is allowed to do other stuff and things (cleanups, reflows, etc.).
That can be done with .setTimeout in browsers or .nextTick in nodejS.
function runAsync( list ) {
(function _worker( method ) {
method();
if( list.length ) {
setTimeout(function() {
_worker( list.shift() );
}, 100);
}
}( list.shift() ));
}
This would get called like
runAsync( commands );
and it would succesive grab the next array-entry (which is assumed a function) and execute it. After that, we check if there are more elements in that entry and if so, grab the next and call the next function. That happens within a setTimeout call and a delay of 100ms. I choosed 100ms here, because its pretty much the timeframe which human beeings won't see any "slow-down" or "lagging".