サーチ…


未来を創る

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object FutureDivider {
    def divide(a: Int, b: Int): Future[Int] = Future {
        // Note that this is integer division.
        a / b
    }
}

簡単に言えば、 divide方法は、商と解決将来作成オーバーa b

将来を成功させる

成功した未来を消費する最も簡単な方法は、未来の価値を得ることです。 mapメソッドを使用することです。いくつかのコードがFutureDividerオブジェクトのdivideメソッドを "Creating a Future"の例からFutureDividerます。コードはの商取得するように見えるためには何が必要でしょうオーバーa b

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
        
        eventualQuotient map {
            quotient => println(quotient)
        }
    }
}

失敗した未来を消費する

将来の計算で例外が作成されることがあり、これによりFutureが失敗することがあります。 "Creating a future"の例では、呼び出しコードが550divideメソッドに渡すとどうなりますか?もちろん、0で除算しようとするとArithmeticExceptionがスローされます。それは消費するコードでどのように処理されますか?実際には、失敗に対処する方法がいくつかあります。

recoverとパターンマッチングで例外を処理します。

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
    
        eventualQuotient recover {
            case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

例外がfailed投影を処理します。ここで例外は未来の値になります。

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
    
        // Note the use of the dot operator to get the failed projection and map it.
        eventualQuotient.failed.map {
            ex => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

未来を一緒にする

前の例では、成功と失敗のケースを処理するFutureの個々の機能を示しました。しかし、通常、両方の機能ははるかに簡潔に処理されます。ここに例があります、もっと現実的なやり方で書かれています:

object Calculator {
    def calculateAndReport(a: Int, b: Int) = {
        val eventualQuotient = FutureDivider divide(a, b)
        
        eventualQuotient map {
            quotient => println(s"Quotient: $quotient")
        } recover {
            case ex: ArithmeticException => println(s"It failed with: ${ex.getMessage}")
        }
    }
}

シーケンシングとトラバース先物

場合によっては、別々の先物で変動額を計算する必要があります。 List[Future[Int]]を持つと仮定しますが、代わりにList[Int]を処理する必要があります。それから問題は、 List[Future[Int]]このインスタンスをFuture[List[Int]]です。この目的のために、 Futureコンパニオンオブジェクトにはsequenceメソッドがあります。

def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.sequence(listOfFuture)

一般的なsequenceは、 F[G[T]]FG制限してG[F[T]]変換する関数型プログラミングの世界で一般的に知られている演算子です。

traverseと呼ばれる代替演算子がありますが、同様の動作をしますが、余分な引数として関数を取ります。 x => xという識別関数をパラメータとして使用すると、 sequence演算子のように動作します。

def listOfFuture: List[Future[Int]] = List(1,2,3).map(Future(_))
def futureOfList: Future[List[Int]] = Future.traverse(listOfFuture)(x => x)

しかし、余分な引数は、指定されたlistOfFuture内の将来の各インスタンスを変更することを可能にします。さらに、最初の議論はFutureリストである必要はありません。したがって、この例を次のように変換することができます。

def futureOfList: Future[List[Int]] = Future.traverse(List(1,2,3))(Future(_))

この場合、 List(1,2,3)は最初の引数として直接渡され、識別関数x => xは関数Future(_)に置き換えられ、同様に各Int値をFutureにラップします。これの利点は、パフォーマンスを向上させるために中間List[Future[Int]]を省略できることです。

複数の先物を組み合わせる - 理解のために

forの理解は、複数の先物の成功した結果に依存するコードのブロックを実行するコンパクトな方法です。

f1, f2, f3 3つのFuture[String]それぞれone, two, threeの文字列が含まれます。

val fCombined = 
    for {
        s1 <- f1
        s2 <- f2
        s3 <- f3
    } yield (s"$s1 - $s2 - $s3")

fCombinedは、すべての先物が正常に完了すると、文字列one - two - threeを含むFuture[String]なります。

暗黙のExectionContextがここで仮定されることに注意してください。

また、理解のためには、flatMapメソッドの単なる構文上の砂糖なので、body内部のFutureオブジェクト構造は、先物で囲まれたコードブロックの並行実行を排除し、シーケンシャルコードにつながることに注意してください。あなたはそれを例に見ています:

val result1 = for {
  first <- Future {
    Thread.sleep(2000)
    System.currentTimeMillis()
  }
  second <- Future {
    Thread.sleep(1000)
    System.currentTimeMillis()
  }
} yield first - second

val fut1 = Future {
  Thread.sleep(2000)
  System.currentTimeMillis()
}
val fut2 = Future {
  Thread.sleep(1000)
  System.currentTimeMillis()
}
val result2 = for {
  first <- fut1
  second <- fut2
} yield first - second

result1オブジェクトで囲まれた値は常に負であり、 result2は正であります。

一般的な理解yield詳細については http://docs.scala-lang.org/tutorials/FAQ/yield.htmlを参照してください。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow