将框架缓冲区运算符与 keepFull 策略相结合:它有什么作用?

Combine framework buffer operator with keepFull strategy: what does it do?

我的测试平台是这样的:

var storage = Set<AnyCancellable>()
override func viewDidLoad() {
    let pub = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
        .scan(0) {i,_ in i+1}
        .buffer(size: 4, prefetch: .keepFull, whenFull: .dropNewest)
        .flatMap(maxPublishers:.max(1)) {
            Just([=10=]).delay(for: 2, scheduler: DispatchQueue.main)
        }
    pub.sink{print([=10=])}.store(in:&storage)
}

结果只是一个缓慢稳定的连续数字流:1 2 3 4 5 6 ...

但这与完全删除 .buffer 行会得到相同的结果。那么缓冲区的作用是什么?换句话说:有人可以给我举个例子,其中带有 .keepFull 预取策略的缓冲区会有所不同吗?

缓冲区“缓冲”值至其大小,同时尊重下游的 back-pressure。

通过这种方式,它在上游发送的内容和下游准备接受的内容之间提供了一个间隙(缓冲区?)。如果下游还没有准备好接受,Timer 只会丢弃值,但是 Buffer 准备好接受(达到其容量 .keepFull,或 always/unlimited 使用 .byRequest 预取策略)

具体来说,在这个例子中,如果我们直接传递来自 Timer 的值,缓冲区将接受所有初始结果(初始结果相隔 0.2 秒),然后填充并进入 steady-state(相隔 2 秒)。

Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
    .buffer(size: 4, prefetch: .keepFull, whenFull: .dropNewest)
    .flatMap(maxPublishers:.max(1)) {
        Just([=10=]).delay(for: 2, scheduler: DispatchQueue.main)
    }

这是 PassthroughSubject 的另一个例子:

let subject = PassthroughSubject<Int, Never>()

let c = subject
           //.buffer(size: 4, prefetch: .keepFull, whenFull: .dropNewest)
           .flatMap(maxPublishers:.max(1)) { 
               Just([=11=]).delay(for: 2, scheduler: DispatchQueue.main) 
           }
           .sink { print([=11=]) }

subject.send(1)
subject.send(2) // 2 would be dropped without the buffer

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
   subject.send(3)
}

话虽这么说,但我并不完全清楚 .keepFull.byRequest.

哪个是好的用例