2

我在异步 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);
    });
});
4

2 回答 2

1

最终答案:

我正在使用递归来遍历命令数组。您向循环函数传递一个命令数组和要调用的最后一个回调(您也可以将希望开始循环的数组的索引作为第四个可选参数传递 - 默认为零)。

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

代码示例

于 2012-11-08T17:01:03.157 回答
0

要让这些函数异步运行,您需要一种调用它们的方法,确保在调用之间,允许浏览器(或实际上任何实现)执行其他操作(清理、重排等)。

这可以.setTimeout在浏览器或.nextTicknodejS 中完成。

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

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

这会被称为

runAsync( commands );

它会连续抓取下一个数组条目(假设是一个函数)并执行它。之后,我们检查该条目中是否有更多元素,如果有,则获取下一个并调用下一个函数。这发生在一个setTimeout呼叫和100ms的延迟内。我在这里选择了100 毫秒,因为它几乎是人类不会看到任何“减速”或“滞后”的时间范围。

于 2012-11-08T16:45:58.407 回答