読者です 読者をやめる 読者になる 読者になる

Screaming Loud

研究・プログラミングなど気づいたことをメモをしています

scalaで非同期処理をつなげるとき

scala

現在、非常に苦戦しております。

非同期処理を順番に行うように実装する方法がなかなか見つかっておりません。

とりあえず、やってみた実装方法はこんな感じ。

 def get(apiUrl: String): Future[JsValue] = {
    WS.url(apiUrl).get().map { response =>
      response.json
    }
  }
  val getFirstRes = get(appUrl)

  val getSecondRes = for {
    res <- getFirstRes
  } yield {
    get(url + res)
  }

  val getThirdRes = for {
    futureRes <- getSecondRes
    res <- futureRes
  } yield get(url + res)

getThirdRes内で2回ジェネレータを使っているのは、
受け取る型がFuture[Future[JsValue]]になってしまっているため、
一回だとFuture[JsValue]のままで読めないからです。

何か他に良いやり方があれば教えてください!

P.S.

コメントで頂いた方法で実装してみました。

// GETメソッドを叩く
def get(apiUrl: String): Future[JsValue] = {
  WS.url(apiUrl).get().map { response =>
    response.json
  }
}

// URLを取得
val apiUrl = {id:Option[String] => {
  id match {
    case Some(s) => "http://hogehoge.com/" + s.toString
    case None => "http://hogehoge.com"
  }
}

// 非同期処理の連鎖
for {
  first <- models.Application.post(appIdUrl(None), appform)
  second <- {
    val url = apiUrl(Option((first \ "id").toString))
    get(url)
  }
  third <- {
    val url = appUrl(Option((second \ "id").toString))
    get(url)
  }
  fourth <- {
    val url = appUrl(Option((third \ "id").toString))
    get(url)
  }
} yield {
  Ok(views.html.apps.index(first, fourth))
}

すごくスッキリしましたー!
ありがとうございました