【问题标题】:How to deal with async functions and collections?如何处理异步函数和集合?
【发布时间】:2014-11-05 09:46:51
【问题描述】:

假设我们有一个函数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 方法比工具/库更感兴趣,反正这些都是可以接受的答案。

【问题讨论】:

  • 提供的示例不是异步的。您的脚本将在 items.map 完成后继续执行,并且在 items.map 完成后,您的结果变量将立即“准备就绪”。
  • 为什么? foo函数的回调可以随时执行。
  • 将代码包装在函数中并使用回调......
  • 在我写了很长的评论解释为什么 foo 不被称为 async 之后,现在我看到你指的是提供给 foo 函数的回调,而不是 foo 本身的调用。对不起这是我的错。我在想,我会给出答案的。
  • @Ravi 将setTimeout 添加到您的回调中以复制异步调用和your code 中断。您的代码之所以有效,是因为您的回调被立即调用。

标签: javascript node.js asynchronous callback


【解决方案1】:

使用 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.
});

【讨论】:

  • 感谢您的回答!这实际上是一个很棒的图书馆。但是你能解释一下它是如何工作的吗?我试图查看async.each的源代码,但我无法真正理解发生了什么,我认为因为整个代码有点hacky。
  • 这不是hacky。它将计算集合中的项目并在收到回调时增加一个数字。如果增加的数字与项目计数相同,则它将返回结果。
  • 哦,我怀疑它,非常聪明,但对我来说仍然听起来很老套
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 2018-12-11
    • 1970-01-01
    • 2019-05-27
    相关资源
    最近更新 更多