斯卡拉 akka 演员:如何将Http响应的结果发送回发送者?

dzhpxtsq  于 2022-11-29  发布在  其他
关注(0)|答案(1)|浏览(157)

我尝试在Akka Actor中执行以下Scala代码。

class FilteringService(implicit timeout: Timeout) extends Actor {

  def receive: PartialFunction[Any, Unit] = {

    case GetProfiles ⇒
      val requester = sender
      def getProfiles = {

        var result = new Array[Profile](0)

        println("[GET-PROFILES] Entered, making request")
        val req = Get("http://localhost:9090/profiles")
        implicit val profileFormat = jsonFormat16(Profile)

        val responseFuture: Future[HttpResponse] = Http().singleRequest(req)
        println("[GET-PROFILES] Entered, request sent")
        responseFuture.onComplete {

          case Success(response) =>
            println("[RES - SUCCESS] Request returned with " + response.status)
            val responseAsProfiles =  Unmarshal(response.entity).to[Array[Profile]]
            responseAsProfiles.onComplete {
            println("[UNMARSH - SUCCESS] Unmarshaling Done!")
            _.get match {
              case profiles: Array[Profile] =>
                println("[UNMARSH - SUCCESS] Sending Profiles message to " + sender())
                requester ! profiles
                println("[UNMARSH - SUCCESS] Message sent to " + sender())
              case _ => println("error")
              }
            }

          case Failure(_)   =>
            sys.error("something wrong")
            //return Future[Array[Profile]]

        }
      }
      println("[RECEIVE] Message GetProfiles received from " + sender().toString())
      getProfiles
      println("[RECEIVE] Message GetProfiles invoked")

  }

当执行元收到消息“获取配置文件”时:
1-它向远程服务器发送请求,因此操作的结果是Future[HttpResponse]
2-如果成功,它将检索响应(JSON数组)并请求将对象解组到Array[Profile]。(Profile模型并不重要)。Unmarshall方法的结果是Future[Array[Profile]]
3-如果成功,我要将结果发送回原始发件人!
我设法做到了这一点,但这是一个技巧,因为我将发送方保存在一个变量中,它在作用域(request)中可见。我知道存在管道模式,因此理论上我可以将responseAsProfiles对象发送回发送方,但该对象是在responseFuture对象的onComplete方法中创建的(当然,我们必须等待它!)
就这样吧!在这种情况下,我如何使用管道模式将结果发送回发送方呢?提前感谢!!!

oyxsuwqo

oyxsuwqo1#

总体思路是使用mapflatMap组合期货,并尽量避免使用onComplete
看看你是否可以将你的代码转换成以下更小的片段,然后组成:

def getRawProfileData(): Future[HttpResponse] = {
 // ... here you make http request
}

def unmarshalProfiles(response: HttpResponse): Future[List[Profile]] = {
  // ... unmarshalling logic
}

def getProfiles(): Future[List[Profile]] = getRawProfileData().flatMape(unmarshalProfiles)

// now from receive block

case GetProfiles ⇒ getProfiles().pipeTo(sender())

相关问题