2017-01-31 14 views
0

У меня есть асинхронное воспроизведение Action, которое извлекает данные из базы данных, используя Slick. И Слик, очевидно, использует Future с, чтобы избежать блокировки:Выполнение независимых запросов Slick внутри одного действия для воспроизведения

def show(id: Long) = Action.async { 
db.run(entities.filter(_.id === id).result.headOption).map { 
    case None => templateFor("NEW_OBJECT") 
    case Some(x) => Ok(x) 
} 
def templateFor(code: String): Future[Result] = { 
    db.run(templates.filter(_.code === code).result.headOption).map { 
    case None => InternalServerError("No template") 
    case Some(x) => Ok(x) 
    } 
} 

Проблема заключается в том, что вызов templateFor() возвращается Future, поэтому весь ActionFuture[Future[Result]] возвращается, который является то, что не ожидал от игры. Итак, я хотел бы избавиться от этого вложенного Future. Простой способ сделать это - Await для его завершения, но я бы хотел избежать ненужной блокировки. Было бы неплохо, если бы я смог взять Future[Result], созданный функцией templateFor(), и вернуть его нетронутым из моего Action, заменив таким образом внешний Future.

+1

'flatMap' это :) – ipoteka

+2

Как @ipoteka сказал: https://cdn.meme.am/cache/instances/folder331/500x/67321331.jpg :) –

ответ

2

Вы можете использовать flatMap для того,

Для любого monandic strutcture, такие как Future[T], flatMap принимает функцию типа T => SomeOtherMonad[K], применяет эту функцию на все элементы, если это монада, а затем разглаживает их дают Future[K].

def show(id: Long) = Action.async { 
    db.run(entities.filter(_.id === id).result.headOption).flatMap { 
    case None => templateFor("NEW_OBJECT") 
    case Some(x) => Future(Ok(x)) 
    } 

    def templateFor(code: String): Future[Result] = 
    db.run(templates.filter(_.code === code).result.headOption).map { 
     case None => InternalServerError("No template") 
     case Some(x) => Ok(x) 
    } 
}