#scala #callback #future #spray
#scala #обратный вызов #будущее #распыление
Вопрос:
У меня такая проблема, когда я хочу вызвать будущее в маршрутизации распыления. Я пробовал ниже, и у меня это работает, и возвращает будущее значение в onComplete
def sendFuture(input):Future[String]= Future {
//some string manipulation
result
}
post {
entity(as[String]) {
input =>
{
onComplete(sendFuture(input)) {
case Success(result) => {
complete("received: " result)
}
case Failure(ex) => complete("An error occurred: " ex.getMessage())
}
}
}
}
Теперь я хочу сделать что-то более сложное. Я хочу выполнить обратный вызов, который принимает аргумент внутри sendFuture и возвращает эту строку в sendFuture, прежде чем sendFuture вернет ее в onComplete . Что-то вроде приведенного ниже:
def sendFuture(input):Future[String]= Future {
//some string manipulation
callBack.call(
(arg:String)=>
{
//some string manipulation
return callBackResult
}
)
//do something with result based on callBackResult
result
}
post {
entity(as[String]) {
input =>
{
onComplete(sendFuture(input)) {
case Success(result) => {
complete("received: " result)
}
case Failure(ex) => complete("An error occurred: " ex.getMessage())
}
}
}
}
Если бы только callBack.call() возвращал строку, но я это функция void / unit.
Ответ №1:
Вам нужно разделить sendFuture
на две функции и использовать map
результат (который является будущим) первой функции, но я не знаю, откуда вы это callback.call
берете, это не Scala Future
. В любом случае логика проста:
Первая часть функции должна содержать обещание, которое ожидало бы результата вашего обратного вызова (все относится к реализации фьючерсов Scala), например:
def computeFirstpart(input: String): Future[String] = {
val promise: Promise[String] = Promise()
// do something with your string
callback.onComplete { case v => promise.complete(v) }
promise.future
}
Эта часть возвращает результат вашего обратного вызова. Теперь вы можете присоединять больше вычислений:
def sendFuture(input: String): Future[String] = {
computeFirstPart(input) flatMap { resultOfFirstPart =>
// do what you need
result // NOTE 1
}
}
ПРИМЕЧАНИЕ 1 Результат должен быть в контексте будущего, вы возвращаете простой тип (например String
) map
, а не flatMap
. Затем используйте его в своей структуре маршрута:
post {
entity(as[String]) { input =>
onComplete(sendFuture(input)) {
case Success(result) =>
complete("received: " result)
case Failure(ex) =>
complete("An error occurred: " ex.getMessage())
}
}
}
}
Комментарии:
1. Я не понимаю, как работает эта часть:
callback.onComplete { case v => promise.complete(v) }
Обратный вызов в моем исходном коде — это класс Java, и у него нет метода «onComplete». Его единственным методом является call(), который принимает функцию, которая принимает строку, но ничего не возвращает