Skip to content

Instantly share code, notes, and snippets.

@tokorom
Created May 23, 2015 13:43
Show Gist options
  • Save tokorom/19ae87acf9db5386c0e1 to your computer and use it in GitHub Desktop.
Save tokorom/19ae87acf9db5386c0e1 to your computer and use it in GitHub Desktop.
SwiftTask chain失敗の検証
NSLog("0. start")
self.request1()
.success { _ -> Task<Progress, Int, Bool> in
NSLog("1-2. request1 callback")
return self.request2()
}
.success { _ in
NSLog("2-2. request2 callback")
}
---------------------------------------------------
func request1() -> Task<Progress, Int, NSError> {
return Task<Progress, Int, NSError> { progress, fulfill, reject, configure in
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
NSLog("1-1. request1 done")
fulfill(1)
}
}
}
func request2() -> Task<Progress, Int, Bool> {
return Task<Progress, Int, Bool> { progress, fulfill, reject, configure in
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
NSLog("2-1. request2 done")
fulfill(1)
}
}
}
@tokorom
Copy link
Author

tokorom commented May 23, 2015

なお、Errorの型が違ってしまうと1つのfailureで全てのErrorを受けることができなくなってしまうので、仕組み的にしかたないと思いました。

@tokorom
Copy link
Author

tokorom commented May 23, 2015

これが実際に起きたケースは、

  1. SwiftTaskベースのAPIClientを作り、そこでは Task<Progress, T, APIError> といった専用のErrorを返す仕組みにしていた
  2. そのAPIClient以外でもSwiftTaskは利用しており、Task<Progress, T, NSError> なシンプルなTaskの実行後に「1」の専用のErrorを返すTaskをchainさせるコードを書いていた

というものです。

Copy link

ghost commented Nov 7, 2015

SwiftTaskに関しての文献が少なく、また、swiftも初心者であるため使い方自体が不安定だったため、大変、勉強になりました。ありがとうございます。

ところで、上記例の解決方法、正解例を教えていただけますでしょうか。よろしくお願いします。

@akio0911
Copy link

akio0911 commented May 7, 2016

enum WrappedError {
    case ByTask1(NSError)
    case ByTask2(Bool)
    case Cancelled
}

func task1() -> Task<(),(),NSError> {
    return Task<(),(),NSError>{ (progress, fulfill, reject, configure) in
        fulfill()
    }
}

func task2() -> Task<(),(),Bool> {
    return Task<(),(),Bool>{ (progress, fulfill, reject, configure) in
        fulfill()
    }
}

private extension Task {
    func _mapError(f: Error -> WrappedError) -> Task<Progress, Value, WrappedError>
    {
        return self.failure({ (error:Error?, isCancelled) -> Task<Progress, Value, WrappedError> in
            if let error = error {
                return Task<Progress, Value, WrappedError>(error: f(error))
            }
            else {
                return Task<Progress, Value, WrappedError>(error: .Cancelled)
            }
        })
    }
}

task1()._mapError(WrappedError.ByTask1).success {
    return task2()._mapError(WrappedError.ByTask2)
}.on (failure: { (error, isCancelled) in
    guard let error = error else { return }
    switch error {
    case let .ByTask1(err):
        print(err)
    case let .ByTask2(flag):
        print(flag)
    case .Cancelled:
        ()
    }
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment