Фьючерсы Scala и обратные вызовы методов с использованием маршрутизации распыления

#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(), который принимает функцию, которая принимает строку, но ничего не возвращает