From eddafa8e8eaebfea82a5ce03f40219bb3781d55a Mon Sep 17 00:00:00 2001 From: Nathan Hosselton Date: Mon, 26 Nov 2018 01:58:06 +0000 Subject: [PATCH] Allow specifying a CatchPolicy in catchOnly(Type) Because for this error type accepting variant of catchOnly it makes sense to want to not catch specific cancellable cases in the type. --- Sources/Catchable.swift | 11 ++++++----- Tests/Core/CatchableTests.swift | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Sources/Catchable.swift b/Sources/Catchable.swift index 7eb77a2..ee73e7d 100644 --- a/Sources/Catchable.swift +++ b/Sources/Catchable.swift @@ -83,14 +83,16 @@ public extension CatchMixin { - Parameter only: The error type to be caught and handled. - Parameter on: The queue to which the provided closure dispatches. - Parameter execute: The handler to execute if this promise is rejected. - - Note: Since this method handles only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ - func catchOnly(_ only: Error.Type, on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Void) -> PMKCascadingFinalizer { + func catchOnly(_ only: Error.Type, on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> PMKCascadingFinalizer { let finalizer = PMKCascadingFinalizer() pipe { switch $0 { case .rejected(let error as Error): + guard policy == .allErrors || !error.isCancelled else { + return finalizer.pending.resolver.reject(error) + } on.async(flags: flags) { body(error) finalizer.pending.resolver.fulfill(()) @@ -171,11 +173,10 @@ public class PMKCascadingFinalizer { - Parameter only: The error type to be caught and handled. - Parameter on: The queue to which the provided closure dispatches. - Parameter execute: The handler to execute if this promise is rejected. - - Note: Since this method handles only specific errors, supplying a `CatchPolicy` is unsupported. You can instead specify e.g. your cancellable error. - SeeAlso: [Cancellation](http://promisekit.org/docs/) */ - public func catchOnly(_ only: Error.Type, on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, _ body: @escaping(Error) -> Void) -> PMKCascadingFinalizer { - return pending.promise.catchOnly(only, on: on, flags: flags) { + public func catchOnly(_ only: Error.Type, on: DispatchQueue? = conf.Q.return, flags: DispatchWorkItemFlags? = nil, policy: CatchPolicy = conf.catchPolicy, _ body: @escaping(Error) -> Void) -> PMKCascadingFinalizer { + return pending.promise.catchOnly(only, on: on, flags: flags, policy: policy) { body($0) } } diff --git a/Tests/Core/CatchableTests.swift b/Tests/Core/CatchableTests.swift index 1a226c5..a003cef 100644 --- a/Tests/Core/CatchableTests.swift +++ b/Tests/Core/CatchableTests.swift @@ -387,6 +387,32 @@ extension CatchableTests { wait(for: [x], timeout: 5) } + + func testCatchOnly_Type_Cancellation_Ignore() { + let x = expectation(description: #file + #function) + + Promise(error: Error.cancelled).catchOnly(Error.self) { _ in + XCTFail() + x.fulfill() + }.catch(policy: .allErrors) { _ in + x.fulfill() + } + + wait(for: [x], timeout: 5) + } + + func testCatchOnly_Type_Cancellation_Handle() { + let x = expectation(description: #file + #function) + + Promise(error: Error.cancelled).catchOnly(Error.self, policy: .allErrors) { _ in + x.fulfill() + }.catch { _ in + XCTFail() + x.fulfill() + } + + wait(for: [x], timeout: 5) + } } private enum Error: CancellableError {