如何处理异步函数和集合?

时间:2014-09-11 12:31:17

标签: javascript node.js asynchronous callback

假设我们有一个函数foo(item, callback)和一个集合items

我要做的是将items中的每个项目替换为执行foo所返回的值,就像Array.map()一样。

但问题出现了:foo的结果在回调中产生,所以我无法在回调本身之外访问它(显然我无法改变foo来满足我的需要)。

您可以尝试像

这样的方法
var results = [];
items.map((function(el) {
    foo(el, function(result) {results.push(time)});
});

但是,您无法知道您的results收藏何时会准备好"。

我完全无能为力。 我该怎么办?模式是什么?

编辑:我对Vanilla Javascript更感兴趣的方法是实现这个,而不是工具/库,无论如何都是可接受的答案。

2 个答案:

答案 0 :(得分:2)

使用async库时,这变得非常简单。

async.each(items, function(el, callback) {
    foo(el, function(result) {
        callback(result);
    });
}, function(results) {
    doSomethingWith(results); //results being an array of the callbacked results.
});

答案 1 :(得分:2)

在香草JS中我会这样做:

var items = ['item 1', 'item 2', 'item 3']

function foo(item, callback) {
    // this is provided just to test the async nature of your callback
    setTimeout(function () {
        callback.call(null, item + ' async')
    }, Math.random() * 5000);
}


var results = [];
var count = 0;
items.forEach(function (element, index, array) {
    foo(element, function (result) {
        results[index] = result;

        // the actual "ready" check
        if (++count == items.length) {
            // here you should notify your code that all items have been replaced

            // after a random number of seconds between 1 and 5 in the current example, it should
            // write ['item 1 async', 'item 2 async', 'item 3 async']
            console.log(results);
        }
    })
});

我不知道这是一种模式还是最好的方式,但我认为简单快捷。请注意,forEach仅适用于IE9 +。对于IE< 9你可以使用jQuery .each或手动编写for循环(但要注意闭包和索引)。