嵌套回调

时间:2012-11-08 16:40:55

标签: javascript asynchronous callback

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

2 个答案:

答案 0 :(得分:2)

最终答案:

我正在使用递归来完成命令数组。 你传递一个循环函数一个命令数组和最后一个要调用的回调函数(你也可以作为第四个可选参数传递你想要启动循环的数组的索引 - 默认为零)。

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

答案 1 :(得分: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 );

并且它将成功获取下一个数组条目(假定为函数)并执行它。之后,我们检查该条目中是否有更多元素,如果有,请抓住下一个并调用下一个函数。这种情况发生在setTimeout来电和延迟 100ms 之间。我在这里选择 100ms ,因为它几乎是人类不会看到任何“减速”或“滞后”的时间框架。