在Q

2013-08-01 30 views
4

中的遍歷承諾在Scala中,我可以獲取一個值列表,在它們之間映射一個未來返回函數,並找回一個未來將這些期貨的價值收集到一個列表中(或者以第一個錯誤失敗) 。更具體地說:在Q

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和朋友的所有重載。

+0

@LeeMeador:Q是一個JavaScript庫 - 我只是給Scala代碼來演示wha我想要這樣做。 –

+0

你確實注意到JavaScript(和Q庫)不是並行執行,而只是異步執行?它只有在doSomething是一個異步任務時纔有用(回調函數和一些並行的東西在後臺運行)。 – Bergi

回答

0

您可以使用無極鏈接+靜態值(而非承諾)的方法和做類似:

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

如果你想這樣的一個橫移功能,您可以輕鬆地實現它自己

希望它有幫助!

+0

傳遞給'.then()'的函數應該返回一個值。你應該在第二個函數中返回'xs'。 – idbehold

+0

謝謝,但我不確定我是否理解,而且這似乎沒有達到我想要的效果 - 看起來它會返回一個包含未來列表的未來? –

+0

@idbehold實際上,當時沒有必要返回一些東西,這只是如果你想將這個承諾轉化爲另一件事的承諾,但在這種情況下就沒有必要。 – mgonto

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

或者有獨立的參數列表中斯卡拉:

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