Почему andThen of Future не связывает результат?

Значение andThen, которое я узнал из этого , является композитором функции.

Скажите, что

f andThen g andThen h

будет равно

h(g(f(x)))

Это означает, что h function получит вход от g(f(x))

Но для andThen in Future все замыкание следующего иThen всегда получает результат от оригинала 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? Я заметил, что эти прикованные и затем будут выполняться последовательно, поэтому причина может быть не для параллельных целей.

Ответ 1

scala.concurrent.Future разработан как компромисс двух асинхронных подходов:

  • Объектно-ориентированный observer, который позволяет связывать асинхронные обработчики
  • Функциональный monad, который предлагает богатые функциональные возможности компоновки.

Чтение Future.andThen docs:

Применяет побочную функцию к результату этого будущего и возвращает новое будущее в результате этого будущего.

Итак, andThen, скорее всего, из вселенной ООП. Чтобы получить аналогичный результат с Function1.andThen, вы можете использовать метод map:

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

andThen отличается от onComplete одной маленькой вещью: в результате Future of andThen все равно возвращает тот же результат, но будет ждать, пока предоставленный наблюдатель не вернет или не выбросит что-то. Вот почему в документах написано:

Этот метод позволяет обеспечить, чтобы обратные вызовы выполнялись в указанный порядок.

Также обратите внимание на третью строку из документов:

Обратите внимание, что если один из прикованных callback-вызовов andThen выдает исключение, это исключение не распространяется на последующие обратные вызовы andThen. Вместо этого последующие обратные вызовы andThen получают исходное значение этого будущего.

Поэтому он ничего не делает с новым результатом Future. Не мог даже испортить его собственным исключением. Это andThen и onComplete просто последовательное и параллельное связывание наблюдателей.