PeakOperation 4.3.0

PeakOperation 4.3.0

Sam OakleyDavid Yates维护。



  • Sam Oakley和David Yates

Peak Operation

PeakOperation是一个Swift微框架,为Operation提供了增强和便利性。它是Peak框架的一部分。

并发操作

ConcurrentOperation 是一个抽象的 Operation 子类,可以异步执行工作。您通过覆盖 execute() 来执行工作,并在完成时调用 finish() 来完成操作。

class MyOperation: ConcurrentOperation {
   override func execute() {
        print("Hello World!")
        finish()
    }
}

let queue = OperationQueue()
let operation = MyOperation()
operation.enqueue(on: queue)

这意味着您可以在 execute() 内执行异步工作,例如执行一个 URLSession 请求。

操作链

Operation 提供了在操作之间添加依赖的能力。PeakOperation建立在这个功能之上,并使其通过一个易于使用的API来实现。

let firstOperation = ...
let secondOperation = ...
        
firstOperation
    .then(do: secondOperation)
    .enqueue()

在上面的例子中,secondOperation 将在 firstOperation 完成后运行。

您还可以在操作链上调用 enqueueWithProgress() 或在单个操作上调用 overallProgress() 来跟踪它们的进度。

let progress: Progress = firstOperation
    .then(do: secondOperation)
    .enqueueWithProgress()

// or

let progress: Progress = secondOperation.overallProgress()

传递结果

在操作之间添加依赖很有用,但操作之间传递结果才是PeakOperation真正闪耀的地方。PeakOperation包括两个您的操作可以遵从的协议:ProducesResultConsumesResult

假设我们有三个操作。第一个产生一个 Result<Int, Error>

class IntOperation: ConcurrentOperation, ProducesResult {
    var output: Result<Int, Error>
    override func execute() {
        output = Result { 1 }
        finish()
    }
}

第二个操作消费一个 Result<Int, Error> 并产生一个 Result<String, Error>。它解包其输入,加1,将其转换为字符串,然后设置其输出。

class AddOneOperation: ConcurrentOperation, ConsumesResult, ProducesResult {
    var input: Result<Int, Error>
    var output: Result<String, Error>
    override func execute() {
        output = Result { "\(try input.get() + 1)" }
        finish()
    }
}

最后一个操作消费一个 Result<String, Error>。它解包它并将输出打印到控制台。

class PrintOperation: ConcurrentOperation, ConsumesResult {
    var input: Result<String, Error>
    override func execute() {
        do {
            print("Hello \(try input.get())!")
        } catch { }
        finish()
    }
}

使用 passesResult(to:),这三个操作可以被串联在一起!

IntOperation()
    .passesResult(to: AddOneOperation())
    .passesResult(to: PrintOperation())
    .enqueue()

    // Hello 2!

只要输入类型与输出类型匹配,就可以在遵循协议的任何操作之间传递结果。

如果有任何操作失败并且其结果为.failure,则结果仍将传递到下一个操作。处理错误的责任在于您,可能通过重新抛出错误适当处理。

class RethrowingOperation: ConcurrentOperation, ConsumesResult, ProducesResult {
    var input: Result<String, Error>
    var output: Result<String, Error>
    override func execute() {
        do {
            let _ = try input.get()
            output = ...
        } catch { 
            output = Result { throw error }
        }
        finish()
    }
}

这样,任何操作都可以失败,并且您仍然可以在最后检索到错误。

let failingOperation = ...
let successfulOperation = ...
let anotherSuccessfulOperation = ...

failingOperation
    .passesResult(to: successfulOperation)
    .passesResult(to: anotherSuccessfulOperation)
    .enqueue()

anotherSuccessfulOperation.addResultBlock { result in
    // result would contain the error from failingOperation 
    // even though the other operations still ran
}

分组

GroupChainOperation接受一个操作和它的依赖操作,并在内部队列上执行它们。操作的最终结果是保留的,并且按照这种方式检查,以使得该操作能够产生类型为Result的结果 - 数据值丢失,但.success/.failure会被保留。这允许您将不同输入/输出不兼容的组连接在一起。

// would otherwise produce String, now produces Void
let group1 = intOperation
    .passesResult(to: stringOperation)
    .group()

// Would otherwise accept Bool, now consumes Void
let group2 = boolOperation
    .passesResult(to: anyOperation)
    .group()

group1
    .passesResult(to: group2)
    .enqueue()

重试

有时一个操作可能会失败。也许您正在处理一个不可靠的Web服务或连接。为此,您可以从RetryingOperation派生子类。这是一种ProducesResult的操作,如果结果为.failure,它将使用给定的retryStrategy闭包再次尝试。

class MyRetryingOperation: RetryingOperation<AnyObject> {
   override func execute() {
        output = Result { throw error }
        finish()
    }
}

let operation = MyRetryingOperation()
operation.retryStrategy = { failureCount in
    return failureCount < 3
}

您可以为retryStrategy提供一个自定义的块。在这里,操作将运行3次,如果最终失败才会停止。

这里提供了2个StrategyBlocks

  • RetryStrategy.none
  • RetryStrategy.repeat(times: Int)

示例

请参阅包含的测试以获取更多示例。还可以查看广泛使用PeakOperation的PeakNetwork

入门

安装

  • 使用Cocoapods,将以下命令添加到Podfile中:pod 'PeakOperation'
  • 在需要的地方导入import PeakOperation

贡献

请阅读CONTRIBUTING.md以了解我们的行为守则以及向我们的pull请求提交的过程。

版本管理

我们使用SemVer进行版本管理。

许可证

本项目受MIT许可证许可 - 请参阅LICENSE.md文件以获取详细信息。

致谢

Peak框架

Peak框架是由3Squared团队创建的一系列开源微框架集合,以其命名的名字Peak District。它由以下组成:

名称 描述
PeakCoreData Core Data提供增强和便利。
PeakNetwork 一个基于Session和PeakOperation构建的重联网件框架,利用了Codable的强大功能。