我正在学习Node.js的开发,并试图将我的大脑包在管理异步“回调地狱”的策略上。我研究的两个主要策略是Caolan McMahon的async模块和Kris Kowal的基于promise的Q模块。
像其他许多人一样,我仍在努力理解何时应该使用一个与另一个。但总的来讲,我发现承诺和基于Q- 代码要 稍微 更直观,所以我在这个方向被移动。
但是,我仍然停留在使用异步模块的功能来管理集合。来自Java和Python背景,在大多数情况下,当我使用集合时,逻辑如下所示:
在客户端JavaScript中,我已经习惯于使用jQuery的map()函数 …传递步骤2的逻辑,并获取步骤3的结果作为返回值。感觉就像相同的基本方法。
节点端异步模块具有类似的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()链中。
then()
我正在努力阐明的最终问题是:在上述代码示例中,我真的需要异步 和 Q吗?我正在学习如何通常用Q样式的Promise链替换异步模块的控制流…但是它还没有“点击”我如何使用基于Promise的方法进行集合的映射或连接。另外,我想了解为什么不能这样做,或者为什么这不是一个好主意。
如果异步和Q在我在上面的示例中使用它们时希望一起工作,那就也可以了。但是,如果我可以单独使用Q,我宁愿不需要额外的库依赖项。
( 对不起,如果我遗漏了非常明显的东西。异步事件驱动模型是一个截然不同的世界,我的头还在游。 )
我真的需要两者吗?
不能。使用promises在集合上映射异步迭代器非常简单,但是它需要两个步骤而不是一个函数调用。首先,集合mapPED以承诺为并行迭代的阵列。然后,将这些承诺输入到Q.all映射集合的一个承诺中。与相比async,结果的顺序得到保证。
map
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,您必须附加一个
concat
.then(function(results) { return Array.prototype.concat.apply([], results); });