Ошибка при попытке преобразовать EventLoopFuture в Type

#swift #event-loop #vapor

#swift #цикл событий #vapor

Вопрос:

Я новичок в кодировании в целом и особенно в концепции фьючерсов, поэтому терпение было бы оценено! Цель следующей функции — проверить, существует ли учетная запись в базе данных PostgreSQL. Если это произойдет, верните пустой UUID; если учетная запись не существует, создайте новую и верните ее UUID. Когда я пытаюсь запустить свой код, Cannot convert return expression of type 'EventLoopFuture<Account.idOut>' to return type 'Account.idOut' рядом со строкой появляется ошибка .map { Account.idOut(id: account.id!) } . Я уже посмотрел здесь и, похоже, не могу найти никакого решения этой проблемы. Любая помощь будет оценена, спасибо!!

 func newAccount(req: Request) throws -> EventLoopFuture<Account.idOut> {
        let input = try req.content.decode(Account.postAccount.self)
        
        //check to see if account already exists
        return Account.query(on: req.db)
            .filter(.$email == input.email)
            .first().map { checkAccount in
                if checkAccount == nil {
                    let id = UUID()
                    let account = Account(id: id, fullName: input.fullName, email: input.email, password: input.password, type: input.type)
                    return account.save(on: req.db)
                        .map { Account.idOut(id: account.id!) }
                } else {
                    return Account.idOut(id: UUID("00000000-0000-0000-0000-000000000000")!)
                }
            }
    }
 

Комментарии:

1. Я голосую за закрытие этого вопроса, потому что его следует задавать в чате сообщества Vapor.

2. @imike звучит здорово. Возможно, это глупый запрос, но не могли бы вы направить меня в чат сообщества, о котором вы говорите? Спасибо 🙂

3. vapor.codes нажимает Chat кнопку в правом верхнем углу

4. @imike, чат является временным и приносит пользу только OP. Ответ на вопрос о SO создает постоянный ресурс и приносит пользу всем, кто впоследствии сталкивается с той же проблемой.

5. @Nick это просто базовые знания о EventLoopFutures kirilltitov.com/en/blog/2019/futures

Ответ №1:

Короче говоря, вам нужно вернуть тот же тип, чтобы удовлетворить компилятор. Это определенно может немного сбить с if толку / else like yours, когда один возвращает future, а другой нет. Способ обойти это — вернуть будущее для обоих таким образом:

     func newAccount(req: Request) throws -> EventLoopFuture<Account.idOut> {
        let input = try req.content.decode(Account.postAccount.self)
        
        //check to see if account already exists
        return Account.query(on: req.db)
            .filter(.$email == input.email)
            .first().flatMap { checkAccount in
                if checkAccount == nil {
                    let id = UUID()
                    let account = Account(id: id, fullName: input.fullName, email: input.email, password: input.password, type: input.type)
                    return account.create(on: req.db)
                        .map { Account.idOut(id: account.id!) }
                } else {
                    return req.eventLoop.future(Account.idOut(id: UUID("00000000-0000-0000-0000-000000000000")!))
                }
            }
    }
 

Важные моменты, на которые следует обратить внимание:

  • Я изменил первое map на a flatMap , поскольку вы возвращаете future внутри
  • Я использовал create вместо save для операции сохранения, поскольку вы предоставляете идентификатор, и это заставляет Fluent создавать модель. (Fluent обычно устанавливает идентификатор для вас)
  • Я завернул учетную запись в req.eventLoop.future — это возвращает EventLoopFuture<Account.idOut> результат, который удовлетворяет компилятору