web-dev-qa-db-ja.com

onCompleteとflatMapof Futureの違いは何ですか?

ReactiveMongoドライバーを使用してScalaアプリケーションを作成しています。データベースにアクセスするメソッドは、常にFuture[T]を返します。次のコードは同等ですか?

onCompleteを使用)

val results: Future[List[Tag]] = Tags.all.toList
results onComplete {
    case Success(list) => //do something with list
    case Failure(t) => //throw the error
}

flatMapを使用)

Tags.all.toList.flatMap(list => //do something with list)

違いは何ですか?

FlatMapは失敗をスローしませんか?そして、flatMaponCompleteのようなコールバックですか、それともTags.all.toListステートメントが完了しないまで待ちますか?

15
alberto adami

疑わしい場合は、タイプに従ってください。

onCompleteUnitを返します。これにより、Futureの結果で何かを行うことができますが、値は返されません。

flatMapリストで何かを行うことができますそして新しいFutureを返します

したがって、flatMapは、複数の先物を連鎖させ、途中でそれらの値を使用して何かを実行し、最後にのみ障害ケースを処理できるため、はるかに強力です。エリック・マイヤーの言葉を使うには:「それはあなたを幸せな道へと導きます」。

だから例えばあなたはすることができます

val finalFuture = results
 .flatMap(x => /* do something and return a future */)
 .flatMap(y => /* do something else and return a future */)
 .flatMap(z => /* do something else and return a future */)
 .map(myresult => /* do something */)

途中で問題が発生した場合、チェーンが早期に切断され、最初のエラーが発生します。

これにより、さらに優れた構文が可能になります

 val finalFuture = for {
    x <- results
    y <- /* do something and return a future */
    z <- /* do something and return a future */
 } yield something(z)

失敗したケースを処理する必要がある場合は、onCompleteを使用できます。または、非同期計算が成功したかどうかに関する情報がすでに含まれているため、Futureを返すだけです。

36