【发布时间】:2020-11-19 22:13:07
【问题描述】:
我开始使用 Vapor 来运行 API,但我无法找到一种优雅的方式来执行以下操作:(1) 加载 Fluent 关系并 (2) 等待响应(3) 响应原始请求之前的 HTTP 回调。
在我将现实生活中的实体转换为行星和恒星以维护 Vapor 文档中的示例之后,这就是我最终编写的代码。它可以工作™️,但我无法实现良好的操作链☹️。
func flagPlanetAsHumanFriendly(req: Request) throws -> EventLoopFuture<Planet> {
Planet(req.parameters.get("planetID"), on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { planet in
// I load the star because I need its ID for the HTTP callback
_ = planet.$star.load(on: req.db).map {
let uri = URI(scheme: "http", host: "localhost", port: 4200, path: "/webhooks/star")
// HTTP Callback
req.client.post(uri) { req in
try req.content.encode(
WebhookDTO(
starId: planet.star.id!,
status: .humanFriendly,
planetId: planet.id!
),
using: JSONEncoder()
)
}
.map { res in
debugPrint("\(res)")
return
}
}
// Couldn't find a way to wait for the response, so the HTTP callback is a side-effect
// and its response is not used in the original HTTP response...
// If the callback fails, my API can't report it.
planet.state = .humanFriendly
return planet.save(on: req.db).map { planet }
}
}
问题 #1。结合2个EventLoopFuture
我的第一个问题是我找不到加载父关系同时将实体保持在范围内的方法。
Planet(req.parameters.get("planetID"), on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap { planet in // planet is in the scope ????
return planet.$star.load(on: req.db) // returns a EventLoopFuture<Void>
}
.map {
// I know that star has been loaded but I lost my `planet` reference ☹️
???
}
我假设有一个运算符应该能够返回 2 个 EventLoopFuture 实例的混合,但我想不通。
问题 #2。将 EventLoopFuture 与辅助 HTTP 请求的响应链接起来
同样,我假设我错过了一个运算符,它允许我在响应原始请求之前等待请求的响应,同时保留对行星的引用。
欢迎提供有关如何通过良好的操作链实现这一点的帮助——当然,如果可能的话——我将非常乐意相应地更新 Vapor 的文档。 ????
【问题讨论】: