Swift中如何等待async/await函数执行完成后再执行后续代码?
Swift中async函数未等待执行完成的解决方法
你遇到的问题是:调用await res.checkExistingUser(email: loginForm.email)后,后续的print("after that")没有等待该函数执行完毕就运行了。这是因为你的checkExistingUser方法虽然标记为async,但内部使用的是闭包回调式的API调用,函数本身会在发起API请求后立即返回,并没有真正挂起协程等待回调完成,导致await无法起到等待作用。
解决思路
把基于闭包的异步API包装成支持async/await的形式,利用Swift的withCheckedThrowingContinuation(或withCheckedContinuation,无错误场景)将回调结果传递给协程,让函数真正等待API请求完成后再返回。
修改后的代码实现
1. 改造ViewModel中的checkExistingUser方法
将原来的闭包回调逻辑替换为async/await调用:
@MainActor final class LoginViewModelImpl: LoginViewModel { @Published var hasError = false @Published private(set) var errorMesg = "" @Published private(set) var isFetching = false @Published private(set) var isLoggedIn = false @Published private(set) var isVerify = false func checkExistingUser(email: String) async { self.isFetching = true let res = UserServiceImpl() do { // 调用包装后的async版本API let apiListingResponse = try await res.checkExistingUserAsync(email: email) print(apiListingResponse) if !apiListingResponse.success { self.hasError = true self.errorMesg = String(localized: String.LocalizationValue(apiListingResponse.error?.message ?? "")) self.isFetching = false return } if apiListingResponse.payload?.message != nil { self.isVerify = false self.hasError = true self.errorMesg = String(localized: String.LocalizationValue("verify_email")) self.isFetching = false return } // 这里添加其他成功场景的逻辑 self.isFetching = false } catch { // 统一处理API请求错误 self.hasError = true self.errorMesg = error.localizedDescription self.isFetching = false } } }
2. 给UserServiceImpl添加async版本的API方法
通过withCheckedThrowingContinuation包装原有的闭包式API:
extension UserServiceImpl { func checkExistingUserAsync(email: String) async throws -> BasedResponse<UserExistModel> { return try await withCheckedThrowingContinuation { continuation in self.checkExistingUser(email: email) .responseDecodable(of: BasedResponse<UserExistModel>.self) { response in switch response.result { case .success(let model): // 成功时返回结果,恢复协程 continuation.resume(returning: model) case .failure(let error): // 失败时抛出错误,恢复协程 continuation.resume(throwing: error) } } } } }
原理说明
withCheckedThrowingContinuation会创建一个“续体”(continuation),暂停当前协程,直到我们手动调用resume方法。- 当API的闭包回调返回结果时,调用
continuation.resume传递成功结果或错误,协程会恢复执行,此时checkExistingUser方法才会真正返回,外部的await才能正确等待整个流程完成。
这样修改后,你原来的调用代码:
await res.checkExistingUser(email: loginForm.email) print("after that") // 现在会等待上面的函数执行完成后再运行
就能正常按顺序执行了。
内容的提问来源于stack exchange,提问作者Mixko
相关产品推荐
相关产品推荐

