Как Future[Seq[Option[Long]]] привести к типу Long
Я только начал работу со Scala и ни как не могу в ней разобраться.
def setReg (sid: String, reg: String) = {
// Получаю Id из БД
val userId = sidDAO.findUserIdBySid(sid).map(us => us.map(_.userId))
// Вношу изменения по полученному Id
userDAO.updateReg(userId, reg)
}
Проблема в том что userId имеет формат Future[Seq[Option[Long]]], а мне нужно передавать Long. Как мне привести к нужному типу?
Ответы (1 шт):
Краткий ответ - приводить не обязательно. Можно сразу передавать.
sidDAO.findUserIdBySid(sid).map(us =>
us.map(u =>
u.userId.map(id =>
userDAO.updateReg(id, reg)
)
)
)
Но обычно нам нужно дождаться успешного результата Future. Для этого внутренние Future нужно вытащить наружу из под слоёв Seq и Option.
a) Убрать Option из коллекции можно с помощью flatten либо flatMap.
val userIds: Seq[Long] = users.map(_.userId).flatten
val userIds: Seq[Long] = users.flatMap(_.userId)
б) Пройтись по коллекции и обработать каждую Future нам поможет Future.traverse.
val updates: Future[Seq[Unit]] =
Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))
в) Вложенные Future[Future[Long]] убираются так же с использованием flatten или flatMap.
Смотрим всё вместе:
sidDAO.findUserIdBySid(sid).flatMap{us =>
val userIds = us.flatMap(_.userId)
Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))
}
Тоже самое с использованием for синтаксиса:
for {
us <- siDAO.findUserIdBySid(sid)
userIds = us.flatMap(_.userId)
_ <- Future.traverse(userIds)(userId => siDAO.updateReg(userId, reg))
} yield ()