我有一系列这样定义的异步方法:
func step1(input: Step1InputData, completion: (Step1OutputData -> Void)) { /* do something */ }
func step2(input: Step1OutputData, completion: (Step2OutputData -> Void)) { /* do something */ }
// etc...
如您所见,
step1
的输出是step2
的输入。这些类型均实现StepData
协议:protocol StepData {}
class Step1InputData : StepData { }
class Step1OutputData : StepData { }
class Step2OutputData : StepData { }
最后,我有这个自定义运算符:
infix operator => { associativity left }
func => <P:StepData, Q:StepData, R:StepData> (left:((P, Q -> Void) -> Void), right:((Q, R -> Void) -> Void)) -> ((P, R -> Void) -> Void) {
return { (x, completion) in
left(x, { y in
right(y, completion)
})
}
}
...这意味着我可以编写以下内容:
let combinedStep = step1 => step2
很棒是因为它具有超强的可读性,并且至关重要的是,它在步骤之间加强了类型安全性。
问题是我希望能够保留
combinedStep
的进度。例如,step1
可以是图像上传,而step2
可以是本地存储写入。如果step2
失败,则下次尝试时,我想从上次中断的地方接听,而不是重新上传图像。当然,可以将任何数量的步骤链接在一起。我可以提出一个系统,该系统具有一系列步骤并管理步骤之间的数据传递,并且能够保持进度,但是,我无法想到一种在保持编译时间的同时做到这一点的方法类型安全。
可以给有更多函数式编程经验的人指出正确的方向吗?
最佳答案
我建议您研究PromiseKit,BrightFutures和ReactiveCocoa之类的框架。
这些框架与您所处的问题和解决方案空间相同,需要进行异步操作,并且它们都提供了多种方法来处理错误和重试。
如果您喜欢其中任何一种,都可以采用它们代替您的自定义实现,并利用大型开发人员社区的支持。或者,您也可以从他们的代码中找到灵感并带回您的手中。
请享用