timeout 은 지정한 시간 내에 값을 발행하지 않으면 선택적으로 지정한 에러를 발행하게 하는 Operator입니다.
굳이 “선택적”이라는 표현을 쓴 이유는, 에러를 지정하지 않으면 정상적으로 .finished 완료이벤트를 발행하기 때문입니다. (이렇게 사용할거라면 timeout을 사용할 이유가 없겠죠?)
enum MyError: Error {
case timeoutError
}
let publisher = PassthroughSubject<String, MyError>()
let timeoutPublisher = publisher.timeout(.seconds(3), scheduler: DispatchQueue.main) {
return .timeoutError // 타임아웃 시 발행할 에러
}
DispatchQueue.main.async {
timeoutPublisher
.sink { completion in
switch completion {
case .finished:
print("finished")
case .failure(let error):
print("error: \\(error)")
}
} receiveValue: { value in
print(value)
}
.store(in: &cancellables)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
publisher.send("I'm not late! :)")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 4) { // 지정시간보다 1초 늦음
publisher.send("I'm too late! :(")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { // 지정시간보다 2초 늦음
publisher.send("Another: I'm too late! :(")
}
// 결과
I'm not late! :)
I'm too late! :(
Another: I'm too late! :(
error: timeoutError
특이한 점은
“I'm too late! :(”
“Another: I'm too late! :(”
값이 구독됐다는 점이에요.
분명히 timeout 연산자는 3초로 지정했는데, 지정한 시간이후에 발행된 값들은 어떻게 구독될 수 있을까요?
그건 바로 timeout의 정확한 기능은 데이터 발행은 모두 구독시키지만 완료이벤트만 지정한 에러(이마저도 에러를 지정하지 않으면 .finished)로 발행하는 것이기 때문이에요!