0

希望实现这一目标:

对 REST API 的 HTTP 请求 -> 解析 -> 对另一个 API 进行异步调用 -> 使用异步调用的结果响应 http req。

目前,代码如下所示:

 def getItems(param: String): LiftResponse = {

    @volatile var resp: LiftResponse = new BadResponse

    param.toLowerCase match {
      case "something" =>
        val req = Async call returning a Future
        req onSuccess {
          case items =>
            resp = new JsonResponse(items map (decompose(_)), S.getResponseHeaders(Nil), S.responseCookies, 200)
        }
        req onFailure {
          case fail => resp = new BadResponse
        }
        resp

      case _ => new OkResponse
    }
  }

但它看起来像实施不佳。

编写上述内容的惯用 Scala 方式是什么?

4

4 回答 4

4

您的代码可能不会做您认为应该做的事情,因为它取决于调度它是否返回 null 或其他内容。LiftResponse 是一个严格的值还是可以推迟?如果严格,那么您将不得不返回Future[LiftResponse]通过映射您的req: Future.

于 2013-08-06T06:12:42.237 回答
4

考虑将 LiftRestHelperRestContinuation.async. 它支持使用延续来暂停请求,直到数据可用。http://demo.liftweb.net/async_rest有一些示例代码。在调用 async continuation 之后,在reply使用结果调用函数之前,请求线程将被释放到线程池中。一旦reply函数被调用,请求将被放回一个线程并将响应发送给客户端。

于 2013-08-08T19:24:05.183 回答
1

我认为您可以尝试通过以下方式内联@volatile var resp

def getItems(param: String): LiftResponse = {

    param.toLowerCase match {
        case "something" =>
            val req = Async call returning a Future
            req.onComplete {
                case Success(items) => new JsonResponse(items map (decompose(_)), S.getResponseHeaders(Nil), S.responseCookies, 200)
                case Failure(t) => new BadResponse
            }
        case _ => new OkResponse
    }

}

- 编辑 -

抱歉,onComplete 返回 Unit,如何使用 Await 来获取未来的结果:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._

def getItems(param: String): LiftResponse = {

    param.toLowerCase match {
        case "something" =>
            val req = Async call returning a Future
            val response = req map { items => 
                new JsonResponse 
            } recover { 
                case t:Throwable => new BadResponse
            }
            Await.result(response, Duration(100, MILLISECONDS))
        case _ => new OkResponse
    }

}
于 2013-08-06T01:18:48.933 回答
0

注意(3 年后):在最近(2016 年 11 月)发布的 Lift3中,您可以使用Piotr Dyraga的“ Lift Futuresnet.liftweb.http._中的请求和会话访问”中所述的。

举个例子,假设你想延迟渲染一个用户列表。
首先,您异步执行数据库查询并获取Future[Seq[User]]此操作的结果。
如果您使用 Lift 2,请合并FutureBinds我在之前的一篇文章中描述的内容,或者如果您使用 Lift3,请导入net.liftweb.http._并执行以下操作:

val allUsers: Future[Seq[User]] = ... // retrieve users from DB

".user-list-async-container" #> allUsers.map { users =>
  ".user-list" #> users.map { user =>
    ".user" #> userBindings(user)
  }
}
于 2016-12-10T22:25:38.800 回答