nsbarb
(Nick)
May 2, 2020, 11:22am
1
I've found a situation in which PassthroughSubject
delivers its values in the wrong order. Is this is working as designed or a bug?
let subject = PassthroughSubject<String, Never>()
let loggedSubject = subject.print()
let printer = loggedSubject.sink {
print("printer: \($0)")
if $0 == "Manual message" {
subject.send("Automatic message")
}
}
let printer2 = loggedSubject.sink {
print("printer2: \($0)")
}
subject.send("Manual message")
When this code is run it prints:
receive subscription: (PassthroughSubject)
request unlimited
receive subscription: (PassthroughSubject)
request unlimited
receive value: (Manual message)
printer: Manual message
receive value: (Automatic message)
printer: Automatic message
receive value: (Automatic message)
printer2: Automatic message
receive value: (Manual message)
printer2: Manual message
It makes sense to me that printer2
receives all its values after printer
. However, I was surprised that printer2
receives its values in the wrong order.
1 Like
the send which you invoke on last line is executed sequentially (synchronized) meaning the first subscription will be called with send and the automatic send in the sink followed immediately with automatic send to the second one before the second subscription received the "manual message".
Combine performs stuff sequently unless you have custom schedulers.
nsbarb
(Nick)
May 2, 2020, 1:25pm
3
Ah yes that's really helped my understanding. Thank you @filiplazov
If I change the loggedSubject
to send values on a serial queue then I get the behaviour I was originally expecting.
I changed loggedSubject
as below
let loggedSubject = subject
.print("Sequential")
.receive(on: DispatchQueue(label: "queue"))
.print("Queued")
and got the output:
Sequential: receive subscription: (PassthroughSubject)
Queued: receive subscription: (ReceiveOn)
Queued: request unlimited
Sequential: request unlimited
Sequential: receive subscription: (PassthroughSubject)
Queued: receive subscription: (ReceiveOn)
Queued: request unlimited
Sequential: request unlimited
Sequential: receive value: (Manual message)
Sequential: receive value: (Manual message)
Queued: receive value: (Manual message)
printer: Manual message
Sequential: receive value: (Automatic message)
Sequential: receive value: (Automatic message)
Queued: receive value: (Manual message)
printer2: Manual message
Queued: receive value: (Automatic message)
printer: Automatic message
Queued: receive value: (Automatic message)
printer2: Automatic message
Staring at that for a while helped me understand how this all works!
Thanks again
1 Like
It takes some tinkering but it is quite simple after you have some experience with it :)