我有一系列这样定义的异步方法:

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失败,则下次尝试时,我想从上次中断的地方接听,而不是重新上传图像。当然,可以将任何数量的步骤链接在一起。

我可以提出一个系统,该系统具有一系列步骤并管理步骤之间的数据传递,并且能够保持进度,但是,我无法想到一种在保持编译时间的同时做到这一点的方法类型安全。

可以给有更多函数式编程经验的人指出正确的方向吗?

最佳答案

我建议您研究PromiseKitBrightFuturesReactiveCocoa之类的框架。

这些框架与您所处的问题和解决方案空间相同,需要进行异步操作,并且它们都提供了多种方法来处理错误和重试。

如果您喜欢其中任何一种,都可以采用它们代替您的自定义实现,并利用大型开发人员社区的支持。或者,您也可以从他们的代码中找到灵感并带回您的手中。

请享用

10-07 23:39