Swift Vapor框架中链式处理双Future的注册重复校验问题
解决方案
要实现用户名、邮箱重复校验及两者均重复的场景处理,我们可以利用Vapor的zip方法将两个独立的异步查询合并,一次性获取校验结果,再根据组合情况返回对应错误或继续执行注册流程。具体步骤如下:
1. 补充错误枚举
首先确保UserError包含三种错误场景:
enum UserError: Error { case usernameTaken case emailTaken case bothUsernameAndEmailTaken }
2. 修改主函数的异步链式逻辑
将原有的单一用户名校验,替换为并行校验用户名和邮箱,再处理所有可能的组合情况:
fileprivate func create(req: Request) throws -> EventLoopFuture<NewSession> { try UserSignup.validate(content: req) let userSignup = try req.content.decode(UserSignup.self) let user = try User.create(from: userSignup) var token: Token! // 并行执行两个校验,用zip合并结果 return checkIfUserExists(userSignup.username, req: req) .zip(checkIfEmailExists(userSignup.email, req: req)) .flatMap { (usernameExists, emailExists) in // 根据两个校验结果的组合返回对应错误,或继续保存用户 switch (usernameExists, emailExists) { case (true, true): return req.eventLoop.future(error: UserError.bothUsernameAndEmailTaken) case (true, false): return req.eventLoop.future(error: UserError.usernameTaken) case (false, true): return req.eventLoop.future(error: UserError.emailTaken) case (false, false): return user.save(on: req.db) } } .flatMap { guard let newToken = try? user.createToken(source: .signup) else { return req.eventLoop.future(error: Abort(.internalServerError)) } token = newToken return token.save(on: req.db) } .flatMapThrowing { NewSession(token: token.value, user: try user.asPublic()) } }
关键逻辑说明
- 并行校验:使用
zip方法可以让checkIfUserExists和checkIfEmailExists两个异步查询同时执行,比串行执行(先查用户名再查邮箱)效率更高,zip会等待两个查询都完成后,返回包含两个结果的元组(usernameExists: Bool, emailExists: Bool)。 - 组合场景处理:通过
switch语句覆盖四种可能的校验结果组合,分别返回对应的友好错误提示,确保每种重复场景都有明确的反馈。 - 原有逻辑保留:用户保存、Token生成及返回
NewSession的逻辑完全保留,符合要求的语法规范。
内容的提问来源于stack exchange,提问作者Tihomir Manushev
相关产品推荐
相关产品推荐

