You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:27:03