多播(_:) 会为每个订阅者创建一个新主题吗

问题描述 投票:0回答:1
在这段代码中,为什么当有 2 个订阅者时

debug: multicast triggered..

 只打印一次。既然苹果说
multicast(_:)
为每个订阅者创建一个新的发布者,那么打印语句不应该被触发两次吗?

import Foundation import Combine var cancellables = Set<AnyCancellable>() let upstreamPublisher = Range(1...3).publisher.delay(for: 1, scheduler: DispatchQueue.main) let sharedSubject = CurrentValueSubject<Int, Never>(-1) // Create a multicast publisher and apply autoconnect let multicastPublisher = upstreamPublisher .multicast({ print("debug: multicast triggered..") return sharedSubject }) .autoconnect() // Subscriber 1 multicastPublisher .sink { value in print("Subscriber 1 received value: \(value)") } .store(in: &cancellables) // Subscriber 2 multicastPublisher .sink { value in print("Subscriber 2 received value: \(value)") } .store(in: &cancellables) // Output //debug: multicast triggered.. //Subscriber 1 received value: -1 //Subscriber 2 received value: -1 //Subscriber 1 received value: 1 //Subscriber 2 received value: 1 //Subscriber 1 received value: 2 //Subscriber 2 received value: 2 //Subscriber 1 received value: 3 //Subscriber 2 received value: 3
    
swift combine
1个回答
0
投票

multicast(_:)

 似乎只调用其闭包一次,而不是在每个订阅者附加到它时重复调用。 (“每次订阅者附加到多播发布者时创建一个新的 
Subject
”的表面概念似乎完全违背了多播的目的,即您只需要对发布者的 
receive<S>(subscriber:)
 方法进行一次调用。)

在我看来,这看起来像是

文档中的错误:multicast(subject:)

multicast(_:)
之间的区别似乎很简单,前者采用
Subject
,而后者采用闭包返回 
Subject


一些观察。考虑一下您的代码片段的再现:

var cancellables = Set<AnyCancellable>() let upstreamPublisher = (1...3).publisher .map { _ in Int.random(in: 0...100) } // Create a multicast publisher let multicastPublisher = upstreamPublisher .multicast { print("debug: multicast triggered…") return PassthroughSubject<Int, Never>() } // Subscriber 1 multicastPublisher .sink { value in print("Subscriber 1 received value: \(value)") } .store(in: &cancellables) // Subscriber 2 multicastPublisher .sink { value in print("Subscriber 2 received value: \(value)") } .store(in: &cancellables) // Connect multicastPublisher.connect() .store(in: &cancellables)
这需要对原始代码片段进行一些修改:

  1. 我个人会避免在这种情况下使用

    autoconnect()

    ,而是推迟 connect()
    ,直到添加了所有订阅者。

    multicast

    函数返回“可连接”发布者的要点是,您可以将连接推迟到代码中的某个未来点。因为我现在推迟了 
    connect()
    ,所以我可以删除 
    delay
    ,这只是为了防止第一个订阅者在第二个订阅者到达之前耗尽序列所必需的。 (显然,如果您愿意,您可以将 
    delay
     添加回来:我的观点只是,如果您推迟 
    connect()
    ,则不需要 
    delay
    。)

  2. 我在随机整数中添加了

    map

    ,因为这可以更好地说明多播的实用性(其中每个订阅者接收相同的值;如果您使用 
    multicast
     删除此再现中的 
    map
    ,则每个订阅者将获得不同系列的随机值)。

  3. 对于此用例,我也更喜欢

    PassThroughSubject

    ,以避免任意哨兵值,但如果您的场景需要的话,显然可以使用 
    CurrentValueSubject

无论如何,结果是:

debug: multicast triggered… Subscriber 2 received value: 96 Subscriber 1 received value: 96 Subscriber 2 received value: 32 Subscriber 1 received value: 32 Subscriber 2 received value: 57 Subscriber 1 received value: 57
    
© www.soinside.com 2019 - 2024. All rights reserved.