web-dev-qa-db-ja.com

andThen of Futureが結果をチェーンしないのはなぜですか?

これから学んだandThenの意味 answer は関数作曲家です。

と言う

_f andThen g andThen h
_

に等しい

_h(g(f(x)))
_

これは、_h function_がg(f(x))から入力を受け取ることを意味します

しかし、andThenFutureの場合、次のすべてのクロージャと、その後、常に元のFutureから結果を受け取ります。

_Future{
    1
}.andThen{ case Success(x) =>
    println(x) // print 1
    Thread.sleep(2000)
    x * 2
}.andThen{ case Success(x) =>
    println(x) // print 1
    Thread.sleep(2000)
    x * 2
}
_

と比較して

_val func: Function1[Int, Int] = { x: Int =>
  x
}.andThen { y =>
  println(y) // print 1
  y * 2
}.andThen { z =>
  println(z) // print 2
  z * 2
}
func(1)
_

Future :: andThen(s)がFutureをチェーンする代わりに、元のFutureからすべて同じ結果を受け取る理由は何ですか?これらのチェーニングされたandThenは順次実行されることがわかりました。その理由は、並列目的ではない可能性があります。

21
Chen OT

scala.concurrent.Futureは、2つの非同期アプローチの妥協案として設計されています。

  1. オブジェクト指向 observer は非同期ハンドラーのバインドを可能にします
  2. 機能 モナド は、豊富な機能合成機能を提供します。

読み込み中 Future.andThenのドキュメント

副作用関数をこのフューチャーの結果に適用し、このフューチャーの結果を持つ新しいフューチャーを返します。

したがって、andThenは、OOP universeからのものである可能性が高いです。Function1.andThenと同様の結果を得るには、 map を使用できます。方法 :

Future(1).map {_ * 2}.map {_ * 2}

andThenonCompleteとは少し異なります。結果として生じるFuture of andThenは同じ結果を返しますが、指定されたオブザーバーが何かを返すかスローするまで待機します。それがドキュメントに書かれている理由です:

このメソッドにより、コールバックが指定された順序で実行されるように強制できます。

また、ドキュメントの3行目に注意してください。

チェーンされたandThenコールバックの1つが例外をスローした場合、その例外は後続のandThenコールバックに伝播されないことに注意してください。代わりに、後続のandThenコールバックには、このフューチャーの元の値が与えられます。

そのため、新しいFutureの結果はまったく何もしません。それ自身の例外でそれを台無しにすることさえできませんでした。このandThenおよびonCompleteは、オブザーバーの順次および並列バインディングのみです。

25
Odomontois

この素敵な議論をまとめてみましょう。

たとえば、tf: Future[T] =...と、f: T => Ug: U => Vという2つの関数があるとします。

vf: Future[V] = tf map f map gを実行できます。vf: Future[V] = tf map (f andThen g)と同じです

fp: PartialFunction[T, U]gp: PartialFunction[U, V]を使用する別の使用例では、tf1: Future[T] = tf andThen fp andThen gpを実行できます。これらの部分関数は、tfが生成する値に対して呼び出され、外部への影響はありません。副作用のみが発生します。このシーケンスはfpを呼び出す前にgpを待ちます。

さらに別の将来の操作であるonCompleteは次のように機能します。f: Try[T] => Uがあると、tf onComplete fを呼び出すと、将来がエラーで終了した場合でもfが呼び出されます。 tf onComplete fの結果はUnit型です。

また、関数fFutureを生成する場合は、flatMapを使用する必要があります。

2
Vlad Patryshev