一尘不染

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

node.js

一般异步与Q

我正在学习Node.js的开发,并试图将我的大脑包在管理异步“回调地狱”的策略上。我研究的两个主要策略是Caolan
McMahon的async模块和Kris
Kowal的基于promise的Q模块。

其他许多人一样,我仍在努力理解何时应该使用一个与另一个。但总的来讲,我发现承诺和基于Q-
代码要 稍微 更直观,所以我在这个方向被移动。

一般映射/连接集合

但是,我仍然停留在使用异步模块的功能来管理集合。来自Java和Python背景,在大多数情况下,当我使用集合时,逻辑如下所示:

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

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

使用异步和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()链中。

我真的需要两者吗?

我正在努力阐明的最终问题是:在上述代码示例中,我真的需要异步
Q吗?我正在学习如何通常用Q样式的Promise链替换异步模块的控制流…但是它还没有“点击”我如何使用基于Promise的方法进行集合的映射或连接。另外,我想了解为什么不能这样做,或者为什么这不是一个好主意。

如果异步和Q在我在上面的示例中使用它们时希望一起工作,那就也可以了。但是,如果我可以单独使用Q,我宁愿不需要额外的库依赖项。

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


阅读 159

收藏
2020-07-07

共1个答案

一尘不染

我真的需要两者吗?

不能。使用promises在集合上映射异步迭代器非常简单,但是它需要两个步骤而不是一个函数调用。首先,集合mapPED以承诺为并行迭代的阵列。然后,将这些承诺输入到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);
});
2020-07-07