2016-08-25 2 views
1

У меня есть два Future[JsArray], f1 и f2, и мне нужно подождать, чтобы оба они были завершены с результатом.Как я могу объединить два Future [JsArray]?

Если они оба успешны, окончательный результат должен быть Success с суммой их содержимого. Если хотя бы один из них не выполняется, окончательный результат должен быть Failure.

Как я могу это сделать?

ответ

0

Одно из решений

  1. Определить map2 функции для Future с:

    def map2[A, B, C](fa: Future[A], fb: Future[B])(g: (A, B) => C) 
           (implicit executor: ExecutionContext): Future[C] = 
        for { 
        a <- fa 
        b <- fb 
        } yield g(a, b) 
    
  2. Определить merge функции для объединения двух JsArray с (т.е. извлечения и конкатенаций элементов и используйте результат для создания нового JsArray):

    def merge(array1: JsArray, array2: JsArray): JsArray = 
        JsArray(array1.elements ++ array2.elements: _*) 
    

    Примечание: вам необходимо указать тип, чтобы передать полученный результат Vector в JsArray's apply method.

  3. Вызов

    map2(f1, f2)(merge) 
    

Пробный запуск в REPL

scala> import spray.json._ 
import spray.json._ 

scala> import scala.concurrent.Future 
import scala.concurrent.Future 

scala> import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.ExecutionContext.Implicits.global 

scala> val f1 = Future(JsArray(JsNumber(1), JsNumber(2))) 
f1: scala.concurrent.Future[spray.json.JsArray] = List() 

scala> val f2 = Future(JsArray(JsNumber(3), JsNumber(4), JsNumber(5))) 
f2: scala.concurrent.Future[spray.json.JsArray] = List() 

scala> map2(f1, f2)(merge).onComplete(println) 
Success([1,2,3,4,5]) 
+1

Это создает массив массивов, вам может понадобиться 'JsArray (jsArray1.elements ++ jsArray2.elements)' –

+0

@AlvaroCarrasco Хорошо и я предполагаю, что это, вероятно, то, чего хочет OP. Я поправлю свой ответ соответственно. – Jubobs

3

Вы можете комбинировать фьючерсы с использованием синтаксиса «для». Что-то вроде:

val f1:Future[Int] = getF1() 
val f2:Future[Int] = getF2() 
val res:Future[Int] = for (
    v1 <- f1; 
    v2 <- f2 
) yield (v1 + v2) 
+0

К сожалению, я отредактировал мой вопрос. Тип не 'Int', а' JsArray'. Я не понимаю, что тип 'res' -' Future [String] 'вместо' Js * '. – Randomize

+0

Как мы «суммируем» JsArrays? – Nyavro

+0

Я этого не знаю.Я ожидал '++' – Randomize

1

Предполагая, что «суммирующих массивы» вы имеете в виду конкатенации их ++, вы хотите сделать:

Future.sequence(Set(getF1,getF2)) map { _ reduce(_ ++ _)} 

последовательность будет иметь успех, если и только если все фьючерсы успеха. Затем мы уменьшаем полученный результат Set на ++ - все его элементы.

+0

он возвращает 'значение ++ не является членом spray.json.JsArray' – Randomize

+1

Я не знаю, какую операцию вы пытаетесь достичь. У вас есть пример? (если вы уже знаете, какую операцию применять, вы можете просто поместить ее вместо '++') – Esardes

2

прямой и простое решение

Будущее поддерживает zip операцию, которая очень удобно.

val f1: Future[JsArray] 
val f2: Future[JsArray] 
val resultF = f1.zip(f2).map {case (a, b) => a ++ b} 

если f1 или f2 терпит неудачу, resultF также не будет с тем же исключением f1 или f2 недостаточности.

необязательно можно удалить скобка

val resultF = f1 zip f2 map { case (f1Result, f2Result) => f1Result ++ f2Result } 
+0

Мне нравится решение «zip» - спасибо за дополнительное предложение – Randomize

Смежные вопросы