Спрей-клиент Я хочу вернуть строку из ответа Json

Извините, но я новичок в Scala. Я читал о фьючерсах и Akka, однако у меня все еще есть проблема с возвратом строки для моего метода.

У меня есть метод getAuthString, который должен возвращать строку аутентификации (или токен). Я использовал спрей Jsonsupport и могу распечатать результат

def getToken(url: String, username: String , password: String) = Future[String]{

import MyJsonProtocol._
import spray.httpx.SprayJsonSupport._

val pipeline: HttpRequest => Future[AuthTokenResult[Entry]] = (addCredentials(BasicHttpCredentials(username, password))
  ~> sendReceive
  ~> unmarshal[AuthTokenResult[Entry]]
  )
val myfutureResponse: Future[AuthTokenResult[Entry]] = pipeline(Get(url))

myfutureResponse onComplete {
      case Success(AuthTokenResult(Entry(Content(authString)):: _)) => println(authString)
      case Failure(error) => println("An error has occured: " + error.getMessage)
    }

это распаковывает json и печатает желаемую authString. Однако печать мне не подходит. Я знаю, что onComplete возвращает модуль. Я хочу вернуть authString, чтобы я мог использовать его где-то еще с другим запросом. Я думаю, что мне придется использовать плоскую карту или карту, но я не уверен, как это сделать. Мне нужно, чтобы мой метод возвращал authString или ошибку.


person Sheggetin    schedule 09.11.2014    source источник


Ответы (1)


Вы не хотите возвращать String, вы хотите возвращать Future[String] - когда что-то асинхронно, единственный способ сделать это не асинхронным - это заблокировать, и это (обычно) пустая трата времени, делающая всю асинхронность бессмысленной.

Я не уверен, почему вы также оборачиваете все это в Future - тривиальные биты вычислений могут происходить сами по себе, мало смысла в том, чтобы навязывать их в отдельный поток. Итак, вы хотите что-то вроде:

def getToken(url: String, ...): Future[String] = {
  ...
  val myFutureResponse: Future[AuthTokenResult[Entry]] = ...
  myFutureResponse map {
    case AuthTokenResult(Entry(Content(authString))::_) => authString
  }
}

Таким образом, вы используете map для преобразования Future в другое Future с помощью вычислений. Это будет «пропускать» ошибки, но вы можете использовать что-то вроде recover или recoverWith, если хотите обрабатывать их определенным образом.

Затем, когда вы хотите использовать свой Future[String] в маршруте Spray, вы можете использовать директивы onSuccess или onComplete:

val myRoute = (path("/somewhere") & parameter("authData") {
  authData =>
    onSuccess(getToken(authData)) {
      authToken =>
        complete("Authed as " + authToken)
    }
  }

Это будет использовать Future правильным асинхронным, реактивным способом, без блокировки.

person lmm    schedule 09.11.2014
comment
Спасибо @Imm за быстрый ответ. Вы дали мне достаточно указаний, и я доволен вашим ответом, однако, простите меня за мое невежество. Если я использую метод маршрутизации, это означает, что весь мой код, который должен выполнять вызов API /url/path+?authToken, должен находиться в одном блоке кода. Почему я не могу использовать что-то вроде Val mytoken = getToken(url, ...), чтобы каждый раз, когда мне нужно сделать запрос API, я мог добавлять токен к своему URL-адресу как часть мой параметр запроса. Вы сказали, что это будет блокировать. Если я это сделаю, проблема в том, что я останусь без кода многократного использования. - person Sheggetin; 09.11.2014
comment
О, я не знал, что вы просто используете спрей-клиент. Вы можете использовать Promise для хранения authToken: val authToken = Promise[String](); authToken.completeWith(getToken()), а затем использовать authToken.future в другом коде. Или вы могли бы использовать актера. Или, может быть, ваш код не обязательно должен быть асинхронным, и в этом случае вы можете просто сделать val authToken = Await.result(getToken(), 30 seconds). В этом случае, возможно, лучше вообще не использовать спрей — он добавляет сложности, необходимой для высокопроизводительного параллельного кода, но в простых случаях можно использовать более простую библиотеку. - person lmm; 09.11.2014