Vapor如何将EventLoopFuture<Type>转为对应Type,删除路由报错求解
问题根因
错误的核心是flatMapThrowing方法的使用场景不对。flatMapThrowing的闭包需要返回非Future类型的普通值,但你在闭包中返回的product.delete(on: req.db).transform(to: .noContent)是EventLoopFuture<HTTPStatus>类型,两者类型不匹配,因此触发编译错误。
修复方案
把内层的flatMapThrowing替换为flatMap即可,flatMap支持闭包返回Future类型,同时也兼容闭包内主动抛出错误的逻辑,修正后代码如下:
func deleteHandler(_ req: Request) throws -> EventLoopFuture<HTTPStatus> { let user = req.auth.get(User.self) return Product.find(req.parameters.get("productID"), on: req.db) .unwrap(or: Abort(.notFound)) .flatMap { product in // 把原来的flatMapThrowing改为flatMap return product.$user.get(on: req.db).flatMap { owner in guard try user?.requireID() == owner.requireID() else { throw Abort(.forbidden) } // 直接返回Future即可匹配类型要求 return product.delete(on: req.db) .transform(to: .noContent) } } }
补充说明
- 不要使用
wait()解决编译问题:wait()会阻塞当前正在运行的EventLoop,违反Vapor的非阻塞设计规则,很容易引发死锁、服务无响应等运行时故障。 - 如果你使用的是Vapor 4+支持async/await的版本,可以改写为异步逻辑,可读性更高:
func deleteHandler(_ req: Request) async throws -> HTTPStatus { guard let user = req.auth.get(User.self) else { throw Abort(.unauthorized) } guard let product = try await Product.find(req.parameters.get("productID"), on: req.db) else { throw Abort(.notFound) } let owner = try await product.$user.get(on: req.db) guard try user.requireID() == owner.requireID() else { throw Abort(.forbidden) } try await product.delete(on: req.db) return .noContent }
内容的提问来源于stack exchange,提问作者Wendell
相关产品推荐
相关产品推荐

