javascript 是否有一种纯粹的基于 Promise 的方法来映射/连接集合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18017980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a pure Promise-based approach for mapping/concatenating collections?
提问by Steve Perkins
async vs. Q generally
异步与 Q 一般
I'm learning Node.js development, and trying to wrap my brain around strategies for managing asynchronous "callback hell". The two main strategies I've explored are Caolan McMahon's asyncmodule, and Kris Kowal's promise-based Qmodule.
我正在学习 Node.js 开发,并试图让我的大脑围绕管理异步“回调地狱”的策略。我探索的两个主要策略是 Caolan McMahon 的async模块和 Kris Kowal 的基于 promise 的Q模块。
Like many other people, I'm still struggling to understand when you should use one vs. the other. However, generally speaking I have found promises and Q-based code to be slightlymore intuitive, so I have been moving in that direction.
像许多其他人一样,我仍在努力理解何时应该使用一种还是另一种。然而,一般来说,我发现 promise 和基于 Q 的代码稍微更直观,所以我一直在朝着这个方向前进。
Mapping/Concatenating collections generally
通常映射/连接集合
However, I'm still stuck using the async module's functions for managing collections. Coming from a Java and Python background, most of the time when I work with a collection, the logic looks like this:
但是,我仍然坚持使用 async 模块的功能来管理集合。来自 Java 和 Python 背景,大部分时间我使用集合时,逻辑如下所示:
- Initialize a new empty collection, in which to store results.
- Perform a for-each loop with the old collection, applying some logic to each element and pushing its result into the new empty collection.
- When the for-each loop ends, proceed to use the new collection.
- 初始化一个新的空集合,在其中存储结果。
- 使用旧集合执行 for-each 循环,对每个元素应用一些逻辑并将其结果推送到新的空集合中。
- 当 for-each 循环结束时,继续使用新集合。
In client-side JavaScript, I've grown accustomed to using jQuery's map() function... passing in that step #2 logic, and getting the step #3 result as a return value. Feels like the same basic approach.
在客户端 JavaScript 中,我已经习惯于使用 jQuery 的map() 函数……传入第 2 步的逻辑,并将第 3 步的结果作为返回值。感觉就像相同的基本方法。
Mapping/Concatenating collections with async and Q
使用 async 和 Q 映射/连接集合
The Node-side async module has similar mapand concatfunctions, but they don't return the concatenated result back at the original scope level. You must instead descend into the callback hell to use the result. Example:
Node 端的 async 模块有类似的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;
Since my other functions are becoming promise-based, I have this code returning a promise object so it can be easily included in a then()
chain.
由于我的其他函数变得基于承诺,我让这段代码返回一个承诺对象,以便可以轻松地将其包含在then()
链中。
Do I really need both?
我真的需要两者吗?
The ultimate question that I'm struggling to articulate is: do I really need both async andQ in the code example above? I'm learning how to replace the async module's control flow with Q-style promise chains generally... but it hasn't yet "clicked" for me how to do mapping or concatenation of collections with a promise-based approach. Alternatively, I'd like to understand why you can't, or why it's not a good idea.
我正在努力阐明的最终问题是:在上面的代码示例中,我真的需要 async和Q 吗?我正在学习如何用 Q 风格的承诺链替换 async 模块的控制流……但我还没有“点击”如何使用基于承诺的方法映射或连接集合。或者,我想了解为什么你不能,或者为什么这不是一个好主意。
If async and Q are meant to work together as I am using them in the example above, then so be it. But I would prefer not to require the extra library dependency if I could cleanly use Q alone.
如果 async 和 Q 意味着像我在上面的示例中使用它们那样一起工作,那么就这样吧。但是,如果我可以单独使用 Q,我宁愿不需要额外的库依赖项。
(Sorry if I'm missing something outrageously obvious. The asynchronous event-driven model is a very different world, and my head is still swimming.)
(对不起,如果我遗漏了一些非常明显的东西。异步事件驱动模型是一个非常不同的世界,我的头还在游泳。)
回答by Bergi
Do I really need both?
我真的需要两者吗?
No. Mapping asynchronous iterators over a collection is quite simple with promises, but it requires two steps instead of one function call. First, the collection is map
pedto an array of promises for the parallel iteration. Then, those promises are fed into Q.all
to make one promise for the mapped collection. In contrast to async
, the order of the result is guaranteed.
不。在一个集合上映射异步迭代器非常简单,但它需要两个步骤,而不是一个函数调用。首先,该集合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);
For concat
, you would have to append a
对于concat
,您必须附加一个
.then(function(results) {
return Array.prototype.concat.apply([], results);
});