Notice
Recent Posts
Recent Comments
Link
study record
[Swift Combine] Future, Deferred 본문
Future
하나의 값을 만들고 끝나거나 실패하는 publisher
final class Future<Output, Failure> where Failure : Error
어떤 작업을 수행하고 비동기적으로 하나의 값을 publish 하고자 할 때 future를 사용한다. 첫번째 value를 보내면 스트림이 바로 끝난다.
Future.Promise를 받는 클로저로 future를 initialize한다. 성공 또는 실패를 가리키는 Result와 함께 promise를 호출한다.
결과가 error인 경우 publishing은 에러와 함께 종료된다.
func generateAsyncRandomNumberFromFuture() -> Future <Int, Never> {
return Future() { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let number = Int.random(in: 1...10)
promise(Result.success(number))
}
}
}
cancellable = generateAsyncRandomNumberFromFuture()
.sink { number in print("Got random number \\(number).") }
// 두번째 값은 출력이 되지 않는다.
let future = Future<Int, Never> { promise in
promise(.success(1))
promise(.success(2))
}
future.sink(receiveCompletion: { print($0) },
receiveValue: { print($0) })
// 출력
// 1
// finished
Integrating with Swift Concurrency
Future는 오직 하나의 요소만 방출하므로 특히 유용하다.
value property를 사용함으로써 쉽게 async await 으로 사용할 수 있다.
let number = await generateAsyncRandomNumberFromFuture().valueprint("Got random number \\(number).")
[주의]
Future Publisher의 경우, 구독자가 없어도 값을 방출한다.
따라서 구독자가 있을 때 값을 방출하도록 하고싶다면 Deferred를 활용하여 구독 후 값을 하나 방출하게끔 해야 한다!
Empty
값을 게시하지 않고 즉시 완료되는 Publisher 이다.
Empty는 아무런 값도 내보내지 않고 즉시 completion 이벤트를 보낼지 선택할 수 있는 Publisher이다.
Empty<String, Never>()
.sink(
receiveCompletion: {
print($0) // finished
},
receiveValue: {
print("receiveValue : \\($0)") // 출력 안함
}
)
let anyPublisher = [1, nil, 3].publisher
.flatMap { value -> AnyPublisher<Int, Never> in
if let value = value {
return Just(value).eraseToAnyPublisher()
} else {
return Empty().eraseToAnyPublisher()
}
}.eraseToAnyPublisher()
anyPublisher.sink(receiveCompletion: { print("AnyPublisher completion: \\($0)") },
receiveValue: { print("value: \\($0)") }
)
Deferred
새 subscriber를 위한 publisher를 만드는 클로저를 제공하기 전에는 subscription을 기다리는 Publisher
struct Deferred<DeferredPublisher> where DeferredPublisher : Publisher
deferred를 사용하면 구독 시점에 따라 값을 다르게 받을 수 있다. 구독을 해야지만 값이 방출되므로 구독 시점에 영향을 받는다.
Deferred { Just(Void()) }
.sink(receiveValue: { print("Diferred") })
→ 아쉬운 점
combine → concurrency로 옮기면 더 좋다! (더 최신식.. 더 간결)
참고
'Swift > Combine' 카테고리의 다른 글
[Combine] 1. Hello Combine! (1) | 2024.08.28 |
---|---|
[Swift] Combine이란? (0) | 2023.01.03 |