您当前的位置: 首页 >  swift

Swift一个小例子带你了解Combine中多重订阅不丢失(auto replay)的方法

发布时间:2020-02-20 09:43:33 ,浏览量:0

引子

Combine中虽然有众多内置Operators,但是要想实现对同一个Publisher多次订阅,且结果不丢失还是比较棘手的,除非实现自定义Publisher,但这不是今天我们的话题 😉

在这里插入图片描述

什么是多重订阅?

多重订阅就是多个订阅者订阅同一个Publisher。

什么是多重订阅不丢失?

不丢失指的是,在有多个订阅者的情况下,无论发生何种情况都可确保每个订阅者都可以接收到每一个消息。

即这是一个自动重发的机制,因为正常情况下Publisher源只会发布一次消息,绝不会为某个订阅者再发一次,你错过了只有怪你自己哦。

举个栗子

拿从网络读取Web数据这个异步操作来说,如果有订阅者在数据返回之后再订阅,它显然无法接收到之前发送的数据:

第一步: 创建发布者

第二步: 订阅者1订阅

第三步: 发布者返回Web数据

第四步: 订阅者1接收到数据

第五步: 订阅者2订阅(接收不到之前的数据)

如上所示,除非使用某种缓存再重发机制,订阅者2就会丢失之前的那次数据。

let url = URL(string: "https://www.csdn.net")!

let p = URLSession.shared.dataTaskPublisher(for: url)
    .share()
    .map(\.data)

	var subscriptions = [AnyCancellable]()

	// 模拟延时一段时间后再订阅
	DispatchQueue.main.asyncAfter(deadline: .now()+5.0){
	    p.sink(receiveValue: {
	    	// 订阅者2不会收到数据
	        print("2: \($0)")
	    }).store(in: &subscriptions)
	}
	
	// 订阅者1立即订阅
	p.sink(receiveValue: {
		// 订阅者1可以收到数据
	    print("1: \($0)")
	}).store(in: &subscriptions)

上面这段简单的代码演示了多重订阅丢失的问题.

那么如何较简单的解决上述问题呢?

在这里插入图片描述

多播前来拯救

Combine中有一个multicast(多播)操作符,用它可以较好地满足上面的问题。

multicast操作符有一个重要的特性,按需手动刷新消息槽.

我们可以在需要时主动为所有订阅者发送消息,而不是让发布者“为所欲为”任性发送…

在这里插入图片描述

废话打住,上代码:

为创建的发布者链接multicast操作符:

let p = URLSession.shared.dataTaskPublisher(for: url)
    .share()
    .map(\.data)
    .multicast {PassthroughSubject()}

注意其返回另一个Publisher,其中的泛型类型不能错!

现在运行代码,是神马结果???

结果就是不会有任何订阅者收到数据,上面说了multicast之后必须由你手动刷新消息槽。

接着在创建订阅者2的结尾加上一句:

// 手动刷新消息槽
p.connect()
    .store(in: &subscriptions)

再次运行代码,你会发现两个订阅者都收到的消息,我们的目标就达到了 😉

总结

Combine中的操作符有很多,要想Combine用的好,用的妙,操作符必须烂熟于胸啊…

再会啦 😉

在这里插入图片描述

关注
打赏
1688896170
查看更多评论

暂无认证

  • 0浏览

    0关注

    107766博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0499s