2012-11-08 89 views
2

我对async javascript没有太多经验。我怎样才能调用命令,而不硬编码命令的数量或使用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); 
    }); 
}); 
+0

只是因为它的回调,这并不意味着它是异步的,所以我有一个很难搞清楚为什么你真的需要这个。你应该澄清为什么你需要这个,我试图投票结束,即使我最初投了票...这是纯粹的假设? –

+0

它看起来像你想要某种排队行为。 – zzzzBov

+0

顺便说一下,代码没有做任何我可以理解的事情...... http://jsfiddle.net/eJS3m/ –

回答

2

最终的答案:

我使用递归去通过命令阵列。 您将loop函数传递给一个命令数组,并将最后一个回调函数传递给您(您也可以将第四个可选参数作为要在其中启动循环的数组的索引 - 默认值为零)。

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

+0

感谢胡安门德斯! – iMoses

+0

如何通过让你传递命令数组来完成它? –

+0

谢谢!我正在构建一个类似shell的代码,并且此代码在管道中执行命令(例如“foo | bar | baz”)并链接stdin和stdout。 – schokocappucino

0

让那些功能运行asyncronously,你需要一种方法通过确保其间的呼叫,一个浏览器(或任何实际执行)被允许做其他的东西和事物来调用它们(清理,回流等)。

这可以通过浏览器中的.setTimeout或nodejS中的.nextTick完成。

function runAsync(list) { 
    (function _worker(method) { 
     method(); 

     if(list.length) { 
      setTimeout(function() { 
       _worker(list.shift()); 
      }, 100); 
     } 
    }(list.shift())); 
} 

这将被调用像

runAsync(commands); 

,它会succesive抓下一个阵列条目(假定一个函数),并执行它。之后,我们检查该条目中是否有更多元素,如果是,请抓住下一个元素并调用下一个函数。这发生在setTimeout呼叫和延迟100ms。我在这里选择了100ms,因为它几乎是人类不会看到任何“减速”或“滞后”的时间表。

+3

我不认为这回答了OP的要求。 – Shmiddty

+0

我同意它没有,但是OP不是很清楚需要什么,请参阅我在问题 –

+0

下的评论嗯,是的,我们在这里可能会遇到“失败”的情况。 – jAndy