2

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);
 });
});
asked Nov 8, 2012 at 16:40
3
  • 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? Commented Nov 8, 2012 at 16:48
  • It looks like you want some sort of queuing behavior. Commented Nov 8, 2012 at 16:49
  • By the way, the code doesn't do anything that I can make sense of... jsfiddle.net/eJS3m Commented Nov 8, 2012 at 17:01

2 Answers 2

1

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

Code Example

answered Nov 8, 2012 at 17:01
Sign up to request clarification or add additional context in comments.

4 Comments

How about finishing it up by letting you pass in the commands array?
Thanks! I'm building something like a shell and this code executes commands in a pipe (for example "foo | bar | baz") and chains stdin and stdout.
You are correct. Use this jsfiddle.net/xuyGT/2 while I'll fix the answer :)
I forgot to add the 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.
0

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".

answered Nov 8, 2012 at 16:45

3 Comments

I don't think this answers what the OP is asking.
I agree that it doesn't, but the OP is not very clear what about what is needed, see my comment under the question
Hmm, yea we might have a case of "fail" here on my part.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.