From 54701bd5f43d5664dea506c7d8641d709faf2c3a Mon Sep 17 00:00:00 2001 From: dougzilla32 Date: Sun, 7 Oct 2018 14:49:29 +0900 Subject: [PATCH 1/2] 'Cancel' for PromiseKit -- provides the ability to cancel promises and promise chains --- Cartfile | 4 +++- Cartfile.resolved | 2 +- Sources/BFTask+Promise.swift | 23 +++++++++++++++++++++-- Tests/TestBolts.swift | 28 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/Cartfile b/Cartfile index cf08ba9..e4e8729 100644 --- a/Cartfile +++ b/Cartfile @@ -1,2 +1,4 @@ -github "mxcl/PromiseKit" ~> 6.0 +#github "mxcl/PromiseKit" ~> 6.0 +github "dougzilla32/PromiseKit" "CoreCancel" + github "BoltsFramework/Bolts-ObjC" ~> 1.9 diff --git a/Cartfile.resolved b/Cartfile.resolved index cc39392..9991ce5 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,2 +1,2 @@ github "BoltsFramework/Bolts-ObjC" "1.9.0" -github "mxcl/PromiseKit" "6.3.3" +github "dougzilla32/PromiseKit" "087b3cf470890ff9ea841212e2f3e285fecf3988" diff --git a/Sources/BFTask+Promise.swift b/Sources/BFTask+Promise.swift index de78655..0311251 100644 --- a/Sources/BFTask+Promise.swift +++ b/Sources/BFTask+Promise.swift @@ -9,8 +9,9 @@ extension Promise { */ public func then(on q: DispatchQueue? = conf.Q.map, body: @escaping (T) -> BFTask) -> Promise { return then(on: q) { tee -> Promise in + let tokenSource = BFCancellationTokenSource() let task = body(tee) - return Promise { seal in + return Promise(cancellableTask: tokenSource) { seal in task.continueWith(block: { task in if task.isCompleted { seal.fulfill(task.result) @@ -20,8 +21,26 @@ extension Promise { seal.reject(PMKError.invalidCallingConvention) } return nil - }) + }, cancellationToken: tokenSource.token) } } } } + +/// Extend BFCancellationTokenSource to be a CancellableTask +extension BFCancellationTokenSource: CancellableTask { + public var isCancelled: Bool { + return token.isCancellationRequested + } +} + +//////////////////////////////////////////////////////////// Cancellable wrapper + +extension CancellablePromise { + /** + The provided closure is executed when this cancellable promise is resolved. + */ + public func then(on q: DispatchQueue? = conf.Q.map, body: @escaping (T) -> BFTask) -> CancellablePromise { + return cancellable(promise.then(on: q, body: body), cancelContext: self.cancelContext) + } +} diff --git a/Tests/TestBolts.swift b/Tests/TestBolts.swift index 6985661..1a63e40 100644 --- a/Tests/TestBolts.swift +++ b/Tests/TestBolts.swift @@ -21,3 +21,31 @@ class TestBolts: XCTestCase { waitForExpectations(timeout: 1) } } + +//////////////////////////////////////////////////////////// Cancellation + +extension TestBolts { + func testCancel() { + let ex = expectation(description: "") + + let value = { NSString(string: "1") } + var task: BFTask? + + let p = firstly { () -> CancellablePromise in + return CancellablePromise() + } + p.then { _ -> BFTask in + task = BFTask(result: value()) + p.cancel() + return task! + }.done { obj in + XCTAssertEqual(obj, value()) + XCTFail() + }.catch(policy: .allErrors) { + $0.isCancelled ? ex.fulfill() : XCTFail() + } + + waitForExpectations(timeout: 1) + } +} + From 19e89ecf993577dd5b2fb7181961d59d977c11be Mon Sep 17 00:00:00 2001 From: dougzilla32 Date: Tue, 16 Oct 2018 11:53:03 +0900 Subject: [PATCH 2/2] 'Cancel' for PromiseKit -- remove cancellable wrappers (they are unnecessary) --- Sources/BFTask+Promise.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/Sources/BFTask+Promise.swift b/Sources/BFTask+Promise.swift index 0311251..96b943a 100644 --- a/Sources/BFTask+Promise.swift +++ b/Sources/BFTask+Promise.swift @@ -34,8 +34,6 @@ extension BFCancellationTokenSource: CancellableTask { } } -//////////////////////////////////////////////////////////// Cancellable wrapper - extension CancellablePromise { /** The provided closure is executed when this cancellable promise is resolved.