- Swift Combine 学习(一):Combine 初印象
- Swift Combine 学习(二):发布者 Publisher
- Swift Combine 学习(三):Subscription和 Subscriber
- Swift Combine 学习(四):操作符 Operator
- Swift Combine 学习(五):Backpressure和 Scheduler
- Swift Combine 学习(六):自定义 Publisher 和 Subscriber
- Swift Combine 学习(七):实践应用场景举例
文章目录
引言
在前面的文章中,已经介绍了 Combine 的基础概念、订阅机制和操作符的使用。本文将深入探讨 Combine 中的异步流程控制,包括 Backpressure 和 Scheduler。这些概念对于编写健壮的异步应用程序非常重要。
订阅的生命周期
Combine 中的订阅遵循以下生命周期:
- 创建订阅:当调用
Publisher的subscribe(_:)方法时,创建一个新的订阅。 - 请求值:订阅者通过
Subscription的request(_:)方法请求值。 - 接收值:发布者通过调用订阅者的
receive(_:)方法发送值。 - 完成或取消:发布者通过两种方式终止:
- 调用
receive(completion:)方法表示完成(成功或失败) - 订阅者调用
cancel()方法取消订阅。
- 调用
Backpressure
Combine 的 Backpressure 技术用于控制发布者(Publisher)向订阅者(Subscriber)发送数据的速率,防止订阅者因处理能力不足而被过多的数据淹没掉。Backpressure 本质上就是一种流量控制机制,确保系统在高负载或高并发情况下仍然能正常工作。在 Combine 中,Backpressure 通过 Subscribers.Demand 来处理:
Subscribers.Demand允许订阅者精确控制它希望接收的元素数量。- 订阅者可以请求有限数量的元素(如
.max(n))、无限元素(.unlimited),或者不请求任何元素(.none)。 - 发布者必须尊重这个需求,不发送超过请求数量的元素。
Demand 的源码:
@frozen public struct Demand : Equatable, Comparable, Hashable, Codable, CustomStringConvertible {
/// A request for as many values as the publisher can produce.
public static let unlimited: Subscribers.Demand
/// A request for no elements from the publisher.
///
/// This is equivalent to `Demand.max(0)`.
public static let none: Subscribers.Demand
/// Creates a demand for the given maximum number of elements.
///
/// The publisher is free to send fewer than the requested maximum number of elements.
///
/// - Parameter value: The maximum number of elements. Providing a negative value for this parameter results in a fatal error.
@inlinable public static func max(_ value: Int) -> Subscribers.Demand
...
}
一个简单的例子:在5秒快速数据生成器可以生成50个值,但由于 Backpressure,实际上只处理了5个值。用 Backpressure 防止数据消费者被过多的数据淹没。
import Combine
import Foundation
import PlaygroundSupport
class FastDataProducer: Publisher {
typealias Output = Int
typealias Failure = Never
private var current = 0
private var timer: Timer?
private var subscriber: AnySubscriber<Int, Never>?
private class FastDataSubscription: Subscription {
private var producer: FastDataProducer?
init(producer: FastDataProducer) {
self.producer = producer
}
func request(_ demand: Subscribers.Demand) {
// 写需求
}
func cancel() {
producer?.timer?.invalidate()
producer?.timer = nil
producer?.subscriber = nil
producer = nil
}
}
func receive<S>(subscriber: S) where S : Subscriber, Failure == S.Failure, Output == S.Input {
self.subscriber = AnySubscriber(subscriber)
subscriber.receive(subscription: FastDataSubscription(producer: self))
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) {
[weak self] _ in
guard let self = self else {
return }
_ = self.subscriber?.receive(self

:Backpressure和 Scheduler&spm=1001.2101.3001.5002&articleId=144837644&d=1&t=3&u=543460fe3ba34f9ba4ff9c4c2545fc7a)
1364

被折叠的 条评论
为什么被折叠?



