Skip to content

Instantly share code, notes, and snippets.

@takezoe
Last active August 29, 2015 14:14
Show Gist options
  • Save takezoe/caf142c96e4f5e8977b5 to your computer and use it in GitHub Desktop.
Save takezoe/caf142c96e4f5e8977b5 to your computer and use it in GitHub Desktop.
Futureの練習問題です

Futureの結果を使って次の処理を行う

2つのWeb APIがあり、1つめのAPIを呼び出して得た結果を使って次のAPIを呼び出す必要があるとします。

ScalaではHTTP通信を行うためのライブラリとしてDispatchというものがあるのですが、このライブラリはノンブロッキングI/Oを使っており、Futureベースのインターフェースを備えています。

例えばGETメソッドでの通信は以下のようにして行うことができます。戻り値はEitherになっており、エラーの場合はLeftThrowableを返す便利仕様ですが、通信に失敗した場合もonSuccessで処理しなくてはいけないのはやや紛らわしいかもしれません。

import dispatch._, Defaults._

def get(endpoint: String): Future[Either[Throwable, String]] = {
  val request = url(endpoint).GET
  Http(request OK as.String).either
}

// こんな感じで使える
get("http://www.yahoo.co.jp/").onSuccess {
  case Left(t)  => t.printStackTrace()
  case Right(s) => println(s)
}

このライブラリを使って2つのWeb APIをシリアルに呼び出す処理を実装してみます。

コールバックで書くとこんな感じ。シンプルでわかりやすいですが、処理が増えるとコールバック地獄になることが目に見えています。

post("http://localhost:8080/get_id").onSuccess {
  case Right(id) => post("http://localhost:8080/recover/" + id)
}

こんな場合にはmapを使います。これならチェーンさせるリクエストが増えてもフラットに記述することができます。

post("http://localhost:8080/get_id").map { id =>
  post("http://localhost:8080/recover/" + id)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment