Skip to content

Commit cbb41e9

Browse files
authored
Merge pull request #1309 from RomanPodymov/v6
Future extensions
2 parents 87b5d53 + 589dc34 commit cbb41e9

3 files changed

Lines changed: 159 additions & 0 deletions

File tree

Sources/Combine.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,42 @@ public extension Promise {
2525
}
2626
}
2727
}
28+
29+
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
30+
public extension Future {
31+
func promise() -> PromiseKit.Promise<Output> {
32+
return .init { [weak self] resolver in
33+
var cancellable: AnyCancellable?
34+
cancellable = self?.sink(receiveCompletion: { completion in
35+
cancellable?.cancel()
36+
cancellable = nil
37+
switch completion {
38+
case .failure(let error):
39+
resolver.reject(error)
40+
case .finished:
41+
break
42+
}
43+
}, receiveValue: { value in
44+
cancellable?.cancel()
45+
cancellable = nil
46+
resolver.fulfill(value)
47+
})
48+
}
49+
}
50+
}
51+
52+
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
53+
public extension Future where Failure == Never {
54+
func guarantee() -> Guarantee<Output> {
55+
return .init { [weak self] resolver in
56+
var cancellable: AnyCancellable?
57+
cancellable = self?.sink(receiveValue: { value in
58+
cancellable?.cancel()
59+
cancellable = nil
60+
resolver(value)
61+
})
62+
}
63+
}
64+
}
2865
#endif
2966
#endif

Tests/CorePromise/CombineTests.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,123 @@ class CombineTests: XCTestCase {
115115

116116
wait(for: [ex], timeout: 1)
117117
}
118+
119+
func testPromiseCombineValue() {
120+
let ex = expectation(description: "")
121+
#if swift(>=4.1)
122+
#if canImport(Combine)
123+
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
124+
let promise = Future<Int, Error> { resolver in
125+
resolver(.success(1))
126+
}.delay(for: 5, scheduler: RunLoop.main).future().promise()
127+
promise.done {
128+
XCTAssertEqual($0, 1)
129+
ex.fulfill()
130+
}.catch { _ in
131+
XCTAssert(false)
132+
ex.fulfill()
133+
}
134+
} else {
135+
ex.fulfill()
136+
}
137+
#else
138+
ex.fulfill()
139+
#endif
140+
#else
141+
ex.fulfill()
142+
#endif
143+
144+
wait(for: [ex], timeout: 10)
145+
}
146+
147+
func testGuaranteeCombineValue() {
148+
let ex = expectation(description: "")
149+
#if swift(>=4.1)
150+
#if canImport(Combine)
151+
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
152+
let guarantee = Future<Int, Never> { resolver in
153+
resolver(.success(1))
154+
}.delay(for: 5, scheduler: RunLoop.main).future().guarantee()
155+
guarantee.done {
156+
XCTAssertEqual($0, 1)
157+
ex.fulfill()
158+
}
159+
} else {
160+
ex.fulfill()
161+
}
162+
#else
163+
ex.fulfill()
164+
#endif
165+
#else
166+
ex.fulfill()
167+
#endif
168+
169+
wait(for: [ex], timeout: 10)
170+
}
171+
172+
func testPromiseCombineThrows() {
173+
let ex = expectation(description: "")
174+
#if swift(>=4.1)
175+
#if canImport(Combine)
176+
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) {
177+
let promise = Future<Int, Error> { resolver in
178+
resolver(.failure(.dummy))
179+
}.delay(for: 5, scheduler: RunLoop.main).map { _ in
180+
100
181+
}.future().promise()
182+
promise.done { _ in
183+
XCTAssert(false)
184+
ex.fulfill()
185+
}.catch { error in
186+
switch error as? Error {
187+
case .dummy:
188+
XCTAssert(true)
189+
default:
190+
XCTAssert(false)
191+
}
192+
ex.fulfill()
193+
}
194+
} else {
195+
ex.fulfill()
196+
}
197+
#else
198+
ex.fulfill()
199+
#endif
200+
#else
201+
ex.fulfill()
202+
#endif
203+
204+
wait(for: [ex], timeout: 10)
205+
}
118206
}
207+
208+
#if swift(>=4.1)
209+
#if canImport(Combine)
210+
/// https://stackoverflow.com/a/60444607/2229783
211+
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
212+
private extension Publisher {
213+
func future() -> Future<Output, Failure> {
214+
return Future { promise in
215+
var ticket: AnyCancellable? = nil
216+
ticket = sink(
217+
receiveCompletion: {
218+
ticket?.cancel()
219+
ticket = nil
220+
switch $0 {
221+
case .failure(let error):
222+
promise(.failure(error))
223+
case .finished:
224+
break
225+
}
226+
},
227+
receiveValue: {
228+
ticket?.cancel()
229+
ticket = nil
230+
promise(.success($0))
231+
}
232+
)
233+
}
234+
}
235+
}
236+
#endif
237+
#endif

Tests/CorePromise/XCTestManifests.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ extension CombineTests {
7474
("testCombineGuaranteeValue", testCombineGuaranteeValue),
7575
("testCombinePromiseThrow", testCombinePromiseThrow),
7676
("testCombinePromiseValue", testCombinePromiseValue),
77+
("testGuaranteeCombineValue", testGuaranteeCombineValue),
78+
("testPromiseCombineThrows", testPromiseCombineThrows),
79+
("testPromiseCombineValue", testPromiseCombineValue),
7780
]
7881
}
7982

0 commit comments

Comments
 (0)