timeout operator in Combine times out even after an event is published

Viewed 686

I'm using the timeout operator in Combine, and my understanding was that it would timeout only if a publisher does not publish an event, but it seems to timeout even if a value is published.

From the docs

A publisher that terminates if the specified interval elapses with no events received from the upstream publisher.

import PlaygroundSupport
import Combine
import Foundation

PlaygroundPage.current.needsIndefiniteExecution = true

let subject = PassthroughSubject<String, Never>()
let cancellable = subject
    .timeout(.seconds(5), scheduler: DispatchQueue.main)
    .sink(
          receiveCompletion: { print ("completion: \($0) at \(Date())") },
          receiveValue: { print ("value: \($0) at \(Date())") }
     )

subject.send("Sending data")

/*
Prints
value: Sending data at 2021-01-06 22:41:12 +0000
completion: finished at 2021-01-06 22:41:17 +0000
*/

Is my understanding wrong with the operator?.

1 Answers

You misunderstood the meaning of the text you quoted. It says that a publisher terminates if the specified interval elapses with no events received, which means, in your example, if there was no value received in the previous 5 seconds.

Documentation also provides a slightly different example that illustrates the point.

So, in other words, if you'd added this to your example:

DispatchQueue.main.async(deadline: .now() + 3) { subject.send("in 3 seconds") }

then you would have had the following output:

value: Sending data at 2021-01-06 22:41:12 +0000
value: in 3 seconds at 2021-01-06 22:41:15 +0000
completion: finished at 2021-01-06 22:41:20 +0000

with the completion arriving 5 seconds after the last value.

Related