Stepwise 2.1

Stepwise 2.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2015年10月
SPM支持 SPM

Kevin Barrett 维护。



  • Kevin Barrett

Stepwise

Stepwise 是一个 Swift 框架,用于异步执行一系列步骤。步骤只是接受输入并返回输出的闭包。输出作为输入传递给链中的下一个步骤。步骤链可取消,处理错误。以下是一个虚构的示例,用于从互联网获取图片并将其缩小为原来的一半

let fetchAndResizeImage = toStep { (url : NSURL) -> UIImage in
    // Fetch the image and create it. Obviously we'd be using Alamofire or something irl.
    guard let imageData = NSData(contentsOfURL: url), image = UIImage(data: imageData) else {
        throw NSError(domain: "com.my.domain", code: -1, userInfo: nil)
    }

    // Pass it to the next step
    return image

}.then { (image : UIImage) -> UIImage in
    // Resize it
    let targetSize = CGSize(width: image.size.width / 2.0, height: image.size.height / 2.0)
    UIGraphicsBeginImageContextWithOptions(targetSize, true, 0.0)
    image.drawInRect(CGRect(origin: CGPoint(x: 0, y: 0), size: targetSize))
    let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // Return it
    return resizedImage
}.then { image in
    // Do something with image here.
    // Set it on a view, pass it to another step, etc.
}

// Having set up the chain of steps, pass in a URL to get fetching. You can also do this one the chain directly by just following up the final `then { }` with `.start(...)`. 
let importantImageURL = NSURL(string: "http://i1.kym-cdn.com/entries/icons/original/000/000/774/lime-cat.jpg")!
fetchAndResizeImage.start(importantImageURL)

第一个步骤由 toStep 函数创建,接受一个闭包(或函数),该闭包只接受一个输入参数。输入参数的类型为 NSURL,如果成功则输出一个 UIImage。第一个步骤从 URL 中获取数据并尝试从中创建一个图像。如果失败,该步骤抛出一个错误。如果一切顺利,通过调用 return image 来解析。

当某个步骤成功解析时,它会将其输出作为输入传递给下一个步骤,该步骤通过调用 then() 创建。在这个例子中,第二个步骤将图像大小调整为原来的一半,然后使用它解析。没有错误情况。

第三个步骤,也是使用 then() 入队的一个示例,仅是带有 Void 输出的步骤的一个例子。带有 Void 输出的步骤不需要 return 任何内容,就像带有 Void 输入的步骤不需要在闭包的开始处声明输入一样。

错误

在上面的例子中,第一个步骤中没有匹配的 catch 与其 throw,但您可以通过调用 onError() 在链中的任何点轻松捕获错误。onError() 接受一个简单的闭包,带有 ErrorType 参数,允许您的代码对步骤生成的错误做出反应。以下是一个快速示例

// prints "ERROR: Error in step 1!"
toStep { () -> String in
    throw NSError(domain: "com.my.domain", code: -1, userInfo: [NSLocalizedDescriptionKey : "Error in step 1!"])
}.then { (input : String) -> Int in
    // This never executes.
    print("I never execute!")
    return input.characters.count
}.onError { error in
    print("ERROR: \((error as NSError).localizedDescription)")
}.start()

要注意的一个重要限制是,目前步骤链只能有一个 onError 闭包。您可以通过在 onError 中对 error 的条件类型转换检查来实现对错误响应的多路复用。

处理器

有时一个步骤可能需要异步解析:这通常发生在步骤进行网络请求或调用带有回调参数的API时。您可以通过向步骤闭包添加额外的Handler参数轻松处理这种情况。而不是从步骤闭包返回值,您可能需要调用handler.pass(output)handler.fail(error)来解析步骤。步骤将等待其中一个方法调用,然后将结果传递给链中的下一个步骤或(如果存在)onError闭包。这看起来是这样的

toStep { (input: [String : AnyObject], handler: Handler<String>) in
    Alamofire.request(.GET, "http://httpbin.org/get", parameters: input)
             .responseString { _, _, result in
                handler.pass(result.value)
             }
}
.then { input in
    print(input) // Request results. Do something with them!
}.start(["foo": "bar"])

取消

取消在Stepwise中是内置的。每个步骤链都有一个返回CancellationToken对象的cancellationToken属性。此对象提供了一个名为cancel的单个方法,用于取消具有此令牌的任何步骤。链中的每个步骤在执行前后都会检查令牌是否已被取消。以下是一个示例

let willCancelStep = toStep { () -> String in
    // Will never execute.
    step.resolve("some result")
}.start()

// Grab the step's token and cancel it.
let token = willCancelStep.cancellationToken
token.cancel(reason: "Canceling for a really good reason.")

您可以选择在取消方法中提供一个用于日志记录目的的String理由。

最后

每个链还提供了一个finally方法,您可以通过调用它来附加一个在链结束时、发生错误或被取消时始终执行的处理器。将类型为ChainState的参数传递给处理器,以指示链的结果。不建议依赖finally来处理链的结果;相反,请使用具有Void输出类型的另一个then步骤。finally是在无论错误或取消状态如何都必须发生的情况中提供的,例如关闭文件资源。以下是一个示例

// In this extremely contrived example, assume we already have an open `NSOutputStream`
// that we must close after our steps complete, regardless of success or erroring out.
let outputStream : NSOutputStream = ...
let someDataURL : NSURL = ...

toStep { () -> NSData in
    guard let someData = NSData(contentsOfURL: someDataURL) else {
        throw NSError(domain: "com.my.domain.fetch-data", code: -1, userInfo: nil)
    }
    return someData
}.then { data in
    // Write our data
    var bytes = UnsafePointer<UInt8>(data.bytes)
    var bytesRemaining = data.length

    while bytesRemaining > 0 {
        let written = outputStream.write(bytes, maxLength: bytesRemaining)
        if written == -1 {
            throw NSError(domain: "com.my.domain.write-data", code: -1, userInfo: nil)
        }

        bytesRemaining -= written
        bytes += written
    }
}.onError { error in
    // Handle error here...
}.finally { resultState in
    // Close the stream here
    outputStream.close()
}.start()

关于闭包签名的注意事项

有时Xcode无法根据步骤闭包内部发生的情况猜测输入和输出类型。这特别适用于您将步骤保存到变量中并在稍后启动它的情况。当您遇到类型错误时,通过在闭包开头添加签名来帮助可怜的Xcode,如下所示(如上例1所示)

let fetchAndResizeImage = toStep { (url : NSURL) -> UIImage in
    // Let's not repeat ourselves
}

// Start the chain
fetchAndResizeImage.start(url)

接受一个Void并返回Void的闭包将是

toStep { () -> Void in
    // Gaze into the void
}.start()

安装

使用Cocoapods!

$ gem install cocoapods

如果还没有,请在您的Podfile中

pod 'Stepwise', '~> 2.1'

测试

本README中的所有示例以及其他示例都可以在库的测试中找到,在StepwiseTests.swift中。

随机好东西

Stepwise由Pagemodo.app精心制作并使用。如果您想使发布到社交网络变得更好,请查看它。

Stepwise.StepDebugLoggingEnabled设置为true,以获取您的步骤中发生的日志消息。

Swift版本

Stepwise使用Swift 2.0。以下表跟踪较旧版本的Swift及其对应的git标签

Swift版本 标签
1.0 swift-1.1
1.1 swift-1.1
1.2 swift-1.2
2.0 2.0+

许可证

Copyright (c) 2014-2015, Webs <[email protected]>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.