我正在使用http4s,我有Try
为响应生成一些json数据:
case GET -> Root / "something" =>
getSomethingTry() match {
case Success(something) => Ok(something)
case Failure(CustomNotFoundException(reason)) => NotFound(reason)
case Failure(CustomConflictException()) => Conflict()
}
此函数正确返回Task[Response]
但是,我想将Try
替换为Future
。匹配不再有效,因为未来可能在比赛时尚未解决。所以,我可以映射未来:
case GET -> Root / "something" =>
getSomethingFuture().map {
something => Ok(something)
}.recover {
case CustomNotFoundException(reason) => NotFound(reason)
case CustomConflictException() => Conflict()
}
但是这会返回Future[Task[Response]]
,这不是http4s想要的。使用Await.result
来取消Future
的打包似乎不合适 - 我认为这可能会导致线程池问题 - 但它确实使代码工作。
http4s接受期货作为任务创建者的参数:
case GET -> Root / "something" =>
Ok(getSomethingFuture())
但这不允许我在出现不同错误时设置不同的状态代码。解决方案可能是对任务执行.recover
,但我看不到明显的方法。
如果出现不同的Future
失败案例,如何调用不同的http4s任务包装器?我需要使用中间件吗?
答案 0 :(得分:2)
假设您使用http4s
0.17及更高版本,则Task
为fs2.Task
。
将Future
转换为Task
然后处理后者很容易:
case GET -> Root / "something" =>
Task.fromFuture(getSomethingFuture())
.flatMap {
something => Ok(something)
}
.handleWith {
case CustomNotFoundException(reason) => NotFound(reason)
case CustomConflictException() => Conflict()
}
但我建议您在整个计划中使用Task
而不是Try
或Future
答案 1 :(得分:-1)
你真的不需要打开未来。 Play框架提供action.async以返回Future。
您可以按以下方式使用
private class CustomFilter : IActionFilter
{
private readonly MainDbContext _mainDbContext;
public CustomFilter(MainDbContext mainDbContext)
{
_mainDbContext = mainDbContext;
}
public void OnActionExecuting(ActionExecutingContext context)
{
var model = _mainDbContext.Groups.ToList();
context.Result = new ViewResult { ViewName = "Index" };
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
}
https://www.playframework.com/documentation/2.6.x/ScalaAsync#returning-futures