代码之家  ›  专栏  ›  技术社区  ›  Ramy Al Zuhouri

如何等待一个空虚的未来?

  •  0
  • Ramy Al Zuhouri  · 技术社区  · 4 年前

    我正在阅读《服务器端Swift Vapor Edition》一书,并试图完成第174页的练习。

    我有一个名为Poll的结构体,定义如下:

    struct Poll: Content, SQLiteUUIDModel, Migration {
        var id: UUID?
        var title: String
        var option1: String
        var option2: String
        var votes1: Int
        var votes2: Int
    }
    

    它使用Fluent映射到SQLite数据库中,我正试图编写一个路由,给出这样的post请求:

    localhost:8080/轮询/删除/

    能够在数据库中找到轮询对象,如果不存在则返回错误,如果存在则删除。这就是我目前解决问题的方法:

    router.post("polls", "delete", UUID.parameter) { req -> Future<Poll> in
        let id = try req.parameters.next(UUID.self)
    
        return Poll.find(id, on: req).map(to: Poll.self) { poll in
            guard let poll = poll else {
                throw Abort(.notFound)
            }
    
            poll.delete(on: req)
    
            return poll
        }
    }
    

    让我们把它分解一下:

    1. 我读取了post请求中传递的UUID(例如。 http://localhost:8080/polls/delete/FBF7FDC2-0ECB-4C1F-AD8F-A62DE68E531B )
    2. 我试着找到民意调查
    3. 如果poll对象为nil(这意味着未找到),则抛出404 not found错误
    4. 如果我找到了,我会删除投票并返回

    这行得通。我可以使用此路线删除民意调查。 但我心里有一些问题:

    1. 难道删除方法仍然失败?(例如,由于SQLite内部错误)
    2. 如果是,我可以等到投票被实际删除后再返回吗?

    问题是delete方法返回一个EventoopFuture类型的对象。如果它是tupeEventoopFuture的一个对象,我就可以很容易地将其映射到投票。但是由于模板参数是Void,如果我这样修改代码:

    router.post("polls", "delete", UUID.parameter) { req -> Future<Poll> in
        let id = try req.parameters.next(UUID.self)
    
        return Poll.find(id, on: req).flatMap(to: Poll.self) { poll in
            guard let poll = poll else {
                throw Abort(.notFound)
            }
    
            return poll.delete(on: req).flatMap(to: Poll.self) { poll -> EventLoopFuture<Poll> in
                return poll
            }
        }
    }
    

    我收到一个语法错误:“无法将'Void'类型的值转换为'EventoopFuture'类型的闭包结果”。看起来我无法将EventoopFuture对象映射到EventoopFuture。问题只是我想等待删除操作完成后再返回。有解决办法吗?

    2 回复  |  直到 4 年前
        1
  •  1
  •   Nick    4 年前

    这个 delete 函数返回 Void 所以你的闭包不应该有参数,这也是你遇到语法错误的原因之一。试试这个:

    router.post("polls", "delete", UUID.parameter) { req -> Future<Poll> in
        let id = try req.parameters.next(UUID.self)
    
        return Poll.find(id, on: req).flatMap { poll in
            guard let poll = poll else {
                throw Abort(.notFound)
            }
    
            return poll.delete(on: req).flatMap{
                return request.future(poll)
            }
        }
    }
    

    将OP的评论与@Rob Napier的回答结合起来,这应该会让你的 poll 回到未来,但只有在 删除 已完成。

    推荐文章