2015-12-07 2 views
0

В чем разница в том, как вы обрабатываете Будущее [Пользователь] в сравнении с Будущим [Опция [Пользователь]]?Как я буду обращаться с Будущим [Пользователь] в сравнении с Будущим [Опция [Пользователь]]?

Я также смущен, так как я думал, что flatMap удаляет параметры, но ограничивается ли они их коллекцией?

ответ

1

Нет, flatMap не удаляется Option. Это ошибочное, но распространенное мнение, навел тот факт, что существует неявное преобразование из Option в Traversable, что позволяет сделать, чтобы такие вещи, как List(Option(1)).flatMap(x => x) (по существу .flatten.)

Вместо этого, думайте о flatMap так же, как вы могли бы сделать с чем-то более похожим на Монаду. Учитывая некоторый тип M[_] и функцию типа A => M[B], произведите M[B]. Итак, для flatMap для работы в этом случае вам нужно будет иметь функцию типа Option[User] => Future[B] для некоторого типа B.

def doSomething(ouser: Option[User]): Future[Output] = { ... 

val res: Future[Output] = futOptUser.flatMap(doSomething) 
+0

Я хочу вариант [User], как мой конечный результат. –

+0

Я не уверен, что «подумайте о FlatMap так же, как вы бы сделали с чем-то более похожим на Monad», - это правильный ответ человеку, который думал о «FlatMap» как о том, что «удаляет» «Option». – ziggystar

+1

@ziggystar Как бы вы так выразились? Самая большая проблема - это глупое неявное преобразование. Это действительно путает проблему на многих фронтах. – wheaties

1

Предлагаю вам прочитать и понять docs.

Короче говоря, без блокировки вы можете:

  • результат будущего преобразования (с использованием map)
  • объединить результаты нескольких фьючерсов (с использованием flatMap)
  • добавить завершения обратного вызова (с использованием onComplete)

Вы можете синхронно дождаться будущего завершения, используя Await, чтобы получить развернутую оценку e, но это обычно не имеет большого смысла (поскольку вы блокируете текущий поток).

Лучше добавить onComplete или onSuccess обратного вызова для вашего будущего (который получит результат распакованных будущегокиевстар в качестве параметра):

val userFuture: Future[Option[User]] = Future { getUserOption() } 
userFuture.onSuccess { 
    case userOpt:Option[User] => userOpt.foreach { user => 
     println(user) // watch out for thread-safety here! 
    }  
} 
+0

Что вы хотите сказать о безопасности потоков здесь? В приложении для воспроизведения, как это может быть проблемой? –

+0

@coolbreeze Просто имейте в виду, что тело и обратный вызов будущего могут выполняться в разных потоках. К сожалению, я не знаком с игрой и, следовательно, не могу сказать, какие ее части потенциально опасны для потоков. – Aivean