是否有一种纯粹的基于 Promise 的方法来映射/连接集合? [英] Is there a pure Promise-based approach for mapping/concatenating collections?

查看:18
本文介绍了是否有一种纯粹的基于 Promise 的方法来映射/连接集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 Node.js 开发,并试图让我的大脑围绕管理异步回调地狱"的策略.我探索的两个主要策略是 Caolan McMahon 的 async 模块和 Kris Kowal 基于承诺的 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 async module, and Kris Kowal's promise-based Q module.

许多其他人一样,我仍在努力理解什么时候应该使用一个与另一个.然而,总的来说,我发现 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 slightly more intuitive, so I have been moving in that direction.

但是,我仍然无法使用异步模块的管理集合的功能.来自 Java 和 Python 背景,大部分时间我处理集合时,逻辑如下所示:

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:

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

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

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.

Node 端的异步模块有类似的 mapconcat 函数,但它们不会在原始范围级别返回连接结果.相反,您必须进入回调地狱才能使用结果.示例:

The Node-side async module has similar map and concat functions, 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:

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

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.

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

The ultimate question that I'm struggling to articulate is: do I really need both async and Q 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,我宁愿不需要额外的库依赖项.

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.

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

推荐答案

我真的需要两者吗?

Do I really need both?

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

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 mapped to 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.

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);
});

这篇关于是否有一种纯粹的基于 Promise 的方法来映射/连接集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆