.sink 和 Subscribers.Sink 有什么区别?
What's the difference between .sink and Subscribers.Sink?
我想用 Future 做一个异步作业。
但是下面的 .sink() 闭包 永远不会被调用。
貌似Future的实例一调用就释放了
Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print([=11=])
})
所以我将 .sink() 闭包 替换为 .subscribe(Subscribers.Sink()) 如下所示。它工作正常。
但问题是我不明白为什么它工作正常。 :(
在我看来是一样的。
这两个代码有什么区别?我什么时候可以使用 .sink(),什么时候不能使用?
Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.subscribe(Subscribers.Sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print([=12=])
}))
提前致谢。
.sink
运算符做三件事:
- 它使用您传递给它的两个闭包创建一个
Subscribers.Sink
。
- 它在上游
Publisher
上调用 subscribe
,传递它创建的 Sink
。
- 它创建了一个
AnyCancellable
,当它被销毁时,取消了 Sink
。它 returns 对此 AnyCancellable
的引用。
AnyCancellable
是引用计数对象。当对 AnyCancellable
的最后一个引用被销毁时,AnyCancellable
本身也被销毁。那时,它调用自己的 cancel
方法。
在您的第一个示例中,您没有保存 .sink
返回的 AnyCancellable
。所以 Swift 立即销毁它,这意味着它立即取消订阅。一秒钟后,您的 asyncAfter
闭包调用 promise
,但订阅已被取消,因此您的 receiveValue
闭包未被调用。
在您的第二个示例中,由于您正在创建 Subscribers.Sink
对象并将其传递给自己 subscribe
,因此不会创建 AnyCancellable
来包装 Sink
。所以没有什么会自动破坏订阅。一秒钟后,asyncAfter
闭包调用 promise
。由于订阅没有被销毁,它仍然存在,所以你的 receiveValue
闭包被调用,然后你的 receiveCompletion
闭包被调用。
所以这实际上是一个非常有趣的使用 Subscribers.Sink
而不是 .sink
运算符。使用 .sink
,您 必须 保存返回的 AnyCancellable
,否则订阅将立即取消。但是通过直接使用 Subscribers.Sink
,您可以创建一个持续到完成的订阅,并且您无需保存任何内容。当订阅完成时(使用 .finished
或 .failure
),Sink
丢弃 Subscription
,这打破了保持它存活的保留周期,因此 Sink
和 Subscription
也被销毁,没有内存泄漏。
我想用 Future 做一个异步作业。 但是下面的 .sink() 闭包 永远不会被调用。 貌似Future的实例一调用就释放了
Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print([=11=])
})
所以我将 .sink() 闭包 替换为 .subscribe(Subscribers.Sink()) 如下所示。它工作正常。 但问题是我不明白为什么它工作正常。 :( 在我看来是一样的。 这两个代码有什么区别?我什么时候可以使用 .sink(),什么时候不能使用?
Future<Int, Never> { promise in
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
promise(.success(1))
}
}
.receive(on: DispatchQueue.main)
.subscribe(Subscribers.Sink(receiveCompletion: { completion in
print(completion)
}, receiveValue: {
print([=12=])
}))
提前致谢。
.sink
运算符做三件事:
- 它使用您传递给它的两个闭包创建一个
Subscribers.Sink
。 - 它在上游
Publisher
上调用subscribe
,传递它创建的Sink
。 - 它创建了一个
AnyCancellable
,当它被销毁时,取消了Sink
。它 returns 对此AnyCancellable
的引用。
AnyCancellable
是引用计数对象。当对 AnyCancellable
的最后一个引用被销毁时,AnyCancellable
本身也被销毁。那时,它调用自己的 cancel
方法。
在您的第一个示例中,您没有保存 .sink
返回的 AnyCancellable
。所以 Swift 立即销毁它,这意味着它立即取消订阅。一秒钟后,您的 asyncAfter
闭包调用 promise
,但订阅已被取消,因此您的 receiveValue
闭包未被调用。
在您的第二个示例中,由于您正在创建 Subscribers.Sink
对象并将其传递给自己 subscribe
,因此不会创建 AnyCancellable
来包装 Sink
。所以没有什么会自动破坏订阅。一秒钟后,asyncAfter
闭包调用 promise
。由于订阅没有被销毁,它仍然存在,所以你的 receiveValue
闭包被调用,然后你的 receiveCompletion
闭包被调用。
所以这实际上是一个非常有趣的使用 Subscribers.Sink
而不是 .sink
运算符。使用 .sink
,您 必须 保存返回的 AnyCancellable
,否则订阅将立即取消。但是通过直接使用 Subscribers.Sink
,您可以创建一个持续到完成的订阅,并且您无需保存任何内容。当订阅完成时(使用 .finished
或 .failure
),Sink
丢弃 Subscription
,这打破了保持它存活的保留周期,因此 Sink
和 Subscription
也被销毁,没有内存泄漏。