Skip to content

Commit

Permalink
Future extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanPodymov committed Mar 10, 2023
1 parent 87b5d53 commit a067d97
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 0 deletions.
37 changes: 37 additions & 0 deletions Sources/Combine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,42 @@ public extension Promise {
}
}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public extension Future {
func promise() -> PromiseKit.Promise<Output> {
return .init { [weak self] resolver in
var cancellable: AnyCancellable?
cancellable = self?.sink(receiveCompletion: { completion in
cancellable?.cancel()
cancellable = nil
switch completion {
case .failure(let error):
resolver.reject(error)
case .finished:
break
}
}, receiveValue: { value in
cancellable?.cancel()
cancellable = nil
resolver.fulfill(value)
})
}
}
}

@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
public extension Future where Failure == Never {
func guarantee() -> Guarantee<Output> {
return .init { [weak self] resolver in
var cancellable: AnyCancellable?
cancellable = self?.sink(receiveValue: { value in
cancellable?.cancel()
cancellable = nil
resolver(value)
})
}
}
}
#endif
#endif
114 changes: 114 additions & 0 deletions Tests/CorePromise/CombineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,118 @@ class CombineTests: XCTestCase {

wait(for: [ex], timeout: 1)
}

func testPromiseCombineValue() {
let ex = expectation(description: "")
#if swift(>=4.1)
#if canImport(Combine)
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
let promise = Future<Int, Error> { resolver in
resolver(.success(1))
}.delay(for: 5, scheduler: RunLoop.main).future().promise()
promise.done {
XCTAssertEqual($0, 1)
ex.fulfill()
}.catch { _ in
XCTAssert(false)
ex.fulfill()
}
} else {
ex.fulfill()
}
#else
ex.fulfill()
#endif
#else
ex.fulfill()
#endif

wait(for: [ex], timeout: 10)
}

func testGuaranteeCombineValue() {
let ex = expectation(description: "")
#if swift(>=4.1)
#if canImport(Combine)
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
let guarantee = Future<Int, Never> { resolver in
resolver(.success(1))
}.delay(for: 5, scheduler: RunLoop.main).future().guarantee()
guarantee.done {
XCTAssertEqual($0, 1)
ex.fulfill()
}
} else {
ex.fulfill()
}
#else
ex.fulfill()
#endif
#else
ex.fulfill()
#endif

wait(for: [ex], timeout: 10)
}

func testPromiseCombineThrows() {
let ex = expectation(description: "")
#if swift(>=4.1)
#if canImport(Combine)
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
let promise = Future<Int, Error> { resolver in
resolver(.failure(.dummy))
}.delay(for: 5, scheduler: RunLoop.main).map { _ in
100
}.future().promise()
promise.done { _ in
XCTAssert(false)
ex.fulfill()
}.catch { error in
switch error as? Error {
case .dummy:
XCTAssert(true)
default:
XCTAssert(false)
}
ex.fulfill()
}
} else {
ex.fulfill()
}
#else
ex.fulfill()
#endif
#else
ex.fulfill()
#endif

wait(for: [ex], timeout: 10)
}
}

/// https://stackoverflow.com/a/60444607/2229783
private extension Publisher {
func future() -> Future<Output, Failure> {
return Future { promise in
var ticket: AnyCancellable? = nil
ticket = sink(
receiveCompletion: {
ticket?.cancel()
ticket = nil
switch $0 {
case .failure(let error):
promise(.failure(error))
case .finished:
break
}
},
receiveValue: {
ticket?.cancel()
ticket = nil
promise(.success($0))
}
)
}
}
}

0 comments on commit a067d97

Please sign in to comment.