【问题标题】:Traversing promises in Q在 Q 中遍历 promise
【发布时间】:2013-08-02 23:37:24
【问题描述】:

在 Scala 中,我可以获取一个值列表,在它们之间映射一个未来返回函数,然后返回一个将这些未来值收集到一个列表中的未来(或因第一个错误而失败)。更具体地说:

import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global

def doSomething(i: Int): Future[Int] = future(i + 1) // Not really doing much.

val incremented = Future.traverse(List(1, 2, 3))(doSomething)

在这种情况下,结果将只是增加的列表:

scala> incremented.onSuccess { case xs => println(xs) }
List(2, 3, 4)

我也可以创建一个期货列表,然后将它们变成一个包含相同结果的未来:

val incremented = Future.sequence(List(1, 2, 3).map(doSomething))

这将给我同样的东西,但它会创建一个额外的中间集合并且会更嘈杂。

我想用Q 中的承诺做这样的事情,看起来Q.all 或多或少是sequence

function doSomething(i) { return Q.fcall(function () { return i + 1; }); }

Q.all([1, 2, 3].map(doSomething)).then(function (xs) { console.log(xs) })

有没有办法让我写一个更像traverse 的版本?这是一个如此基本的操作,似乎必须有办法做到这一点,但这是我与 Q 的第一个下午,我仍在处理fcall 和朋友的所有重载。

【问题讨论】:

  • @LeeMeador:Q 是一个 JavaScript 库——我只是提供 Scala 代码来演示我想要做什么。
  • 您确实注意到 JavaScript(和 Q 库)没有并行执行,而只是异步执行?只有当doSomething 是一个异步任务(在后台运行回调和一些并行的东西)时,它才会有所帮助。

标签: javascript asynchronous future promise q


【解决方案1】:

不是直接回答你的问题,但 AngularJS 使用了一个极其简化的 Q 版本 ($q),所以你必须自己实现这个行为。

这是一种方法:

var traverse = function(fn /*values*/) {
  var values = _.rest(arguments);
  var promises = _.map(values, fn);
  return $q.all(promises);
};

完整示例:http://plnkr.co/edit/PGp7QbQYMjOknJwSEn8E

或者在 Scala 中使用单独的参数列表:

  var traverse = function(/*values*/) {
    var values = arguments;
    return function(fn) {
      var promises = _.map(values, fn);
      return $q.all(promises);  
    }
  };

完整示例:http://plnkr.co/edit/pWoGGaZobbx61tAmUWr9?p=preview

【讨论】:

    【解决方案2】:

    您可以对方法使用 Promise Chaining + 静态值(而不是 Promise)并执行以下操作:

    Q.all([1,2,3])
        .then(function(xs) {
          return _(xs).map(doSomething) 
        })
        .then(function(xs) {
          console.log(xs);
        });
    

    如果你想要一个这样的遍历函数,你可以自己轻松实现

    希望对你有帮助!

    【讨论】:

    • 传递给.then() 的函数应该返回一个值。您应该在第二个函数中返回 xs
    • 谢谢,但我不确定我是否理解,这似乎并没有达到我想要的效果——它看起来返回一个包含期货列表的未来?
    • @idbehold 其实 then 没有必要返回一些东西,只是如果你想把这个承诺转换成另一个东西的承诺,但在这种情况下没有必要。
    • @TravisBrown 是的,就是这样,你是对的,这不是你所需要的,你可以使用 Q.all([Q.when(1) , Q.when(2), Q.when(3)] 然后按原样继续,但它太冗长了。
    猜你喜欢
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2023-03-29
    • 2015-08-26
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多