17

异步与 Q 通常

我正在学习 Node.js 开发,并试图围绕管理异步“回调地狱”的策略展开思考。我探索的两个主要策略是 Caolan McMahon 的async模块和 Kris Kowal 的基于 promise 的Q模块。

许多其他人一样,我仍在努力理解何时应该使用一个与另一个。但是,一般来说,我发现 Promise 和基于 Q 的代码直观一些,所以我一直在朝着这个方向前进。

通常映射/连接集合

但是,我仍然坚持使用 async 模块的功能来管理集合。来自 Java 和 Python 背景,大多数时候我使用集合时,逻辑如下所示:

  1. 初始化一个新的空集合,用于存储结果。
  2. 对旧集合执行 for-each 循环,对每个元素应用一些逻辑并将其结果推送到新的空集合中。
  3. 当 for-each 循环结束时,继续使用新的集合。

在客户端 JavaScript 中,我已经习惯于使用 jQuery 的map() 函数……传入第 2 步的逻辑,并将第 3 步的结果作为返回值。感觉就像是相同的基本方法。

使用 async 和 Q 映射/连接集合

节点端异步模块具有类似的mapconcat函数,但它们不会将连接的结果返回到原始范围级别。您必须改为进入回调地狱才能使用结果。例子:

var deferred = Q.defer();

...

var entries = [???]; // some array of objects with "id" attributes

async.concat(entries, function (entry, callback) {
    callback(null, entry.id);
}, function (err, ids) {
    // We now have the "ids" array, holding the "id" attributes of all items in the "entries" array.
    ...
    // Optionaly, perhaps do some sorting or other post-processing on "ids".
    ...
    deferred.resolve(ids);
});

...

return deferred.promise;

由于我的其他函数正变得基于 Promise,因此我让这段代码返回一个 Promise 对象,以便它可以轻松地包含在then()链中。

我真的需要两者吗?

我正在努力表达的最终问题是:在上面的代码示例中,我真的需要 asyncQ 吗?我正在学习如何用 Q 风格的承诺链替换异步模块的控制流......但它还没有“点击”我如何使用基于承诺的方法进行集合的映射或连接。或者,我想了解您为什么不能,或者为什么这不是一个好主意。

如果我在上面的示例中使用 async 和 Q 是为了一起工作,那么就这样吧。但如果我可以单独使用 Q,我宁愿不需要额外的库依赖项。

对不起,如果我遗漏了一些非常明显的东西。异步事件驱动模型是一个非常不同的世界,我的脑袋还在游泳。

4

1 回答 1

27

我真的需要两者吗?

不会。使用 Promise 在集合上映射异步迭代器非常简单,但它需要两个步骤而不是一个函数调用。首先,集合被mapped到一个并行迭代的 Promise 数组。然后,这些承诺被输入为Q.all映射集合做出一个承诺。与 相比async,结果的顺序是有保证的。

var entries = […]; // some array of objects with "id" attributes

var promises = entries.map(function(object) {
    return asyncPromiseReturingFunction(object);
}); // the anonymous wrapper might be omitted
return Q.all(promises);

对于concat,您必须附加一个

.then(function(results) {
     return Array.prototype.concat.apply([], results);
});
于 2013-08-02T13:45:19.347 回答