是否有一种纯粹基于Promise的方法来映射/连接集合



异步与Q的比较

我正在学习Node.js的开发,并试图将我的大脑包裹在管理异步"回调地狱"的策略上。我探索的两个主要策略是Caolan McMahon的异步模块和Kris Kowal的基于承诺的Q模块。

和许多其他人一样,我仍然在努力理解什么时候应该使用其中一种与另一种。然而,总的来说,我发现promise和基于Q的代码稍微更直观,所以我一直在朝着这个方向前进。

通常映射/连接集合

然而,我仍然使用异步模块的函数来管理集合。来自Java和Python背景,大多数时候当我处理集合时,逻辑看起来是这样的:

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

在客户端JavaScript中,我已经习惯了使用jQuery的map()函数。。。传入步骤#2逻辑,并得到步骤#3的结果作为返回值。感觉是一样的基本方法。

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

节点端异步模块具有类似的map和concat函数,但它们不会在原始作用域级别返回连接的结果。相反,您必须进入回调地狱才能使用结果。示例:

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()链中。

我真的需要两者吗

我正在努力阐明的最终问题是:在上面的代码示例中,我真的需要异步Q吗?我正在学习如何用Q型承诺链取代异步模块的控制流。。。但我还没有"了解"如何使用基于promise的方法映射或连接集合。或者,我想了解为什么你不能,或者为什么这不是一个好主意。

如果async和Q要像我在上面的例子中使用它们一样一起工作,那就顺其自然吧。但如果我可以干净地单独使用Q,我宁愿不需要额外的库依赖关系。

很抱歉,我错过了一些非常明显的东西。异步事件驱动的模型是一个非常不同的世界,我的脑袋还在游动。

我真的需要两者吗?

没有。通过promise在集合上映射异步迭代器非常简单,但它需要两个步骤,而不是一个函数调用。首先,将集合map添加到并行迭代的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);
});

最新更新