Как ждать будущего, которое возвращается пустым? - PullRequest
2 голосов
/ 01 февраля 2020

Я слежу за книгой "Server Side 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
}

Он отображается в базе данных SQLite с помощью Fluent, и я пытаюсь написать маршрут, который дал запрос на публикацию, подобный этому:

localhost: 8080 / polls / delete /

Может найти объект опроса в базе данных, вернуть ошибку, если она не существует, или удалить, если она существует. Вот как я решаю проблему на данный момент:

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. Я прочитал UUID, переданный в запросе на отправку (например, http://localhost: 8080 / polls / delete / FBF7FDC2-0ECB-4C1F-AD8F-A62DE68E531B )
  2. Я пытаюсь найти опрос
  3. Если объект опроса равен нулю (что означает что он не был найден), я выкидываю ошибку 404 not found
  4. Если я найду его, я удаляю опрос и возвращаю его

Это работает. Я могу удалить опросы, используя этот маршрут. Но у меня есть несколько вопросов:

  1. Может быть, метод удаления все еще не работает? (например, из-за внутренней ошибки SQLite)
  2. Если да, можно ли подождать, пока опрос действительно будет удален, прежде чем его вернуть?

Проблема заключается в том, что метод delete возвращает объект типа EventLoopFuture. Если бы это был объект типа EventLoopFuture, я мог бы легко сопоставить его с опросом. Но так как аргумент шаблона равен 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 »в закрывающий тип результата« EventLoopFuture »». Похоже, я не могу сопоставить объект EventLoopFuture с EventLoopFuture. Проблема только в том, что я хочу дождаться завершения операции удаления, прежде чем вернуться. Любое решение?

1 Ответ

1 голос
/ 01 февраля 2020

Функция 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)
        }
    }
}

Принимая комментарии ОП к ответу @Rob Napier на борту, это должно преобразовать ваш poll в будущее, но только после того, как delete завершится.

...