当前位置: 首页 > 知识库问答 >
问题:

从Actor返回实际结果而不是Promise/Future

白迪
2023-03-14

我正在尝试用Akka / Scala编写一个actor,调用HTTP REST API并将结果发送回调用actor。API 可能会返回结果的集合/向量,必须首先将其转换为内部供应商中性格式,以便将来可以更改供应商,而无需对代码进行太多更改。大多数代码都在工作,但我不知道如何解压缩并发送内部向量。

这是我拥有的代码,它向调用的Actor返回一个Promise。我想返回的是最终映射操作中创建的实际向量:

class RESTActor extends Actor with ActorLogging with JsonSupport {

  final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))
  val http = Http(context.system)

  import akka.pattern.pipe
  import context.dispatcher

  override def receive: Receive = {
    case query: String => {
      val requester = sender
      var uri = Uri(Settings.autoCompleteURL).withQuery(Query(Map("query" -> query)))

      sender! http
        .singleRequest(HttpRequest(HttpMethods.GET, uri = uri))
        .flatMap(response =>
          response.status match {
            case status if status.isSuccess() => Unmarshal(response.entity).to[VendorResponse].map(_.result.map(x => VendorNeutralResponse(x.id, x.field)))

            case _ => response.entity.toStrict(5.seconds).map { entity =>
              val body = entity.data.decodeString("UTF-8")
              log.warning(errorMessage(response, body))
              Left(errorMessage(response, body))
            }

          })
    }

  }

主叫演员:

pathPrefix("search") {
          get {
            parameter("query") { query =>
              {
                complete(restActor.ask(query)) //Doesn't work as the reply is a promise

              }
            }
          }
        }

如何在重启器中更改上述代码,以将实际结果发送回,而不是发送未来或promise?

编辑:根据我自己的研究和@micha和@cyrille-corpet的建议修改代码后,下面的代码工作了:

pathPrefix("search") {
          get {
            parameter("query") { query =>
              {
                onComplete(gisRouter.ask(query)) {
                  case Success(resp: Future[Vector[VendorNeutralResponse]]) => {
                    resp.map(println)
                    complete("ok")
                  }
                  case Failure(e) => complete(e.toString)
                }

              }
            }
          }
        }

看起来我还是能从我的演员那里得到一个< code >未来的回应。我如何让参与者用实际数据而不是< code >未来来回应?

共有2个答案

郗鹏
2023-03-14

你可以使用map来做它:

pathPrefix("search") {
  get {
    parameter("query") { query =>
      restActor.ask(query) map {
        case Success(resp) => ...
        case Failure(e) => ...
      }
    }
  }
}

编辑:目前你的演员回答未来。尝试重构它,使它返回未包装的值:

class RESTActor extends Actor with ActorLogging with JsonSupport {

  final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))
  val http = Http(context.system)

  import akka.pattern.pipe
  import context.dispatcher

  private def handleHttpResponse = {
    case status if status.isSuccess() => Unmarshal(response.entity).to[VendorResponse].map(_.result.map(x => VendorNeutralResponse(x.id, x.field)))

    case _ => response.entity.toStrict(5.seconds).map { entity =>
      val body = entity.data.decodeString("UTF-8")
      log.warning(errorMessage(response, body))
      Left(errorMessage(response, body))
    }

  }

  override def receive: Receive = {
    case query: String => {
      val requester = sender
      var uri = Uri(Settings.autoCompleteURL).withQuery(Query(Map("query" -> query)))

      http.singleRequest(HttpRequest(HttpMethods.GET, uri = uri)).flatMap(response =>
          response.status map handleHttpResponse ) pipeTo requester
    }

  }
孔建柏
2023-03-14

您可以使用< code>onComplete函数,该函数将< code>Future[T]作为输入,并返回一个< code>Directive1[Try[T]],因此您可以按如下方式使用:

pathPrefix("search") {
  get {
    parameter("query") { query =>
      onComplete(restActor.ask(query)) {
        case Success(resp) => ...
        case Failure(e) => ...
      }
    }
  }
}

编辑从您的actor返回的内容,您应该将< code>http.singleRequest的结果通过管道发送给发送方,而不是告诉它:

http.singleRequest(...).flatMap(...) pipeTo requester

这样,只有在未来得到解决后,才会进行实际的告诉()。

 类似资料:
  • 问题内容: 背景 我正在尝试学习承诺,并且我有一个希望改进的承诺链。 问题 在学习如何链接承诺时,我看不到为什么有人愿意返回承诺而不是返回其价值。 以下面的示例为例,该示例使用了Promise链接: 在这里,我必须链接2次。但是,如果我直接从方法中返回结果而不是返回Promise,则可能会执行以下操作: 问题 如您所见,我有些困惑。 鉴于实际上是异步的,是否有可能实现与我的第二个代码示例中的代码相

  • 我想从一个MariaDB数据库获取数据,并通过Maven安装了MariaDB JDBC连接器。下面的代码将数据的参数而不是实际的行/单元格数据添加到组合框中(请参见代码段,第10行)。这就是我要解决的问题。如果重要的话,我的表由1个int和4个varchar组成。 代码段(带行计数):

  • 问题内容: 我想获取动态生成的HQL查询的结果计数,而无需实际获取结果列表。说我的查询是这样的: 我在Hibernate文档中看到: 您可以计算查询结果的数量而无需返回它们: 我怀疑应该用查询替换 .... ,但这不起作用,因为HQL不支持FROM中的子选择。 那么,我应该如何计算动态生成的HQL查询的结果?我认为通过执行它并获取结果列表的.size()可能是不必要的开销。 干杯! 更新: 我使用

  • 我知道有很多与此相关的问题,但我似乎找不到一个能帮助我解决问题的答案。 我正在使用os.walk()循环浏览主文件夹中的子文件夹,其中包含文件夹和文件。 因此,我使用这段代码根据子文件夹名称创建一个新的文本文件。但是,这将返回folder/.txt,这意味着dirs将返回“/”,而files将返回['file.txt','file2.txt']。 如何修复它,使dirs返回['主文件夹/传递文件夹

  • 我试图了解异步/等待如何与promise一起工作。 据我所知,await应该是阻塞的,在上面的代码中,它似乎阻塞了返回带有原语

  • 我试图用Java创建一个XPath表达式(8,默认XPath实现)。我正在做以下工作: 我在同一级别的文档中有多个PartyId节点,因为它的父节点是重复的。我得到了结果,但只有一个节点。(第一)。 补充信息:如果我在表达式的末尾写[$k],比如[1]或[2],我得到了我的元素,但是我需要它们。:( 但是,如果我正在测试同一个XPath,例如http://www.freeformatter.com