如何在PromiseKit链式请求的done块中获取首个请求的userModel(不存self)
解决Promise链中跨块传递数据的问题
你遇到的核心问题是在Promise链式调用中需要保留之前步骤的结果,同时不想依赖实例变量来存储。其实用**元组+Promise.value()**来包装同步数据是完全合理的方案,这正是Promise链中传递多份上下文数据的标准做法,不用觉得别扭~
下面是修改后的代码,完全移除了self.userModel和self.initModel的使用,通过在每个then块中返回包含所需数据的元组来传递上下文:
func callService(completionHandler: @escaping (Result<UserModel>) -> Void) { SandboxService.createsandboxUser() // 第一步:拿到userModel后,调用初始化接口,返回包含userModel和initModel的元组Promise .then { userModel -> Promise<(UserModel, InstallationModel)> in return SandboxService.initializeClient(publicKey: self.keyPairs.publicKey) .then { initModel in // 用Promise.value把同步的元组包装成Promise,符合返回要求 return Promise.value((userModel, initModel)) } } // 第二步:接收(userModel, initModel)元组,调用设备服务接口,返回包含三者的元组Promise .then { (userModel, initModel) -> Promise<(UserModel, InstallationModel, DeviceServerResponseModel)> in return SandboxService.deviceServerServiceCaller( authKey: initModel.token.token, apiKey: userModel.apiKey, privaKey: self.keyPairs.privateKey ) .then { serverResponseModel in return Promise.value((userModel, initModel, serverResponseModel)) } } // 第三步:接收所有上下文数据,调用会话服务接口 .then { (userModel, initModel, serverResponseModel) -> Promise<UserModel> in return SandboxService.sessionServiceCaller( authKey: initModel.token.token, apiKey: userModel.apiKey, privaKey: self.keyPairs.privateKey ) } .done { userModel in completionHandler(Result.success(userModel)) } .catch { error in completionHandler(Result.error(error)) } }
关键说明:
- 用元组打包上下文:每个
then块完成后,把当前步骤的结果和之前需要保留的数据(比如userModel、initModel)打包成元组,这样后续的then块就能直接获取所有需要的数据。 Promise.value()的合理性:因为then块要求返回Promise类型,而元组是同步的非Promise值,用Promise.value()把它包装成已完成的Promise是完全符合Promise规范的操作,这不是“不合理方案”,反而是链式调用中传递同步上下文的标准方式。- 移除实例变量依赖:这样代码更纯粹,避免了实例变量带来的状态污染问题,尤其是在并发调用该方法时,不会出现多个请求互相覆盖
self.userModel的情况。
如果某些步骤不需要保留所有之前的数据,你可以调整元组的内容,只保留后续步骤需要的字段,让代码更简洁。
内容的提问来源于stack exchange,提问作者Emre Önder
相关产品推荐
相关产品推荐

