Комбинирование оператора буфера фреймворка со стратегией keepFull: что он делает? - PullRequest
0 голосов
/ 05 августа 2020

Мой тестовый стенд выглядит так:

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($0).delay(for: 2, scheduler: DispatchQueue.main)
        }
    pub.sink{print($0)}.store(in:&storage)
}

Результат - просто медленный непрерывный поток чисел подряд: 1 2 3 4 5 6 ...

Но это тот же результат, который вы получили бы, если бы полностью удалили строку .buffer. Так какой же цели служит буфер? Другими словами: может ли кто-нибудь привести мне пример, в котором буфер с политикой предварительной выборки .keepFull имеет значение?

1 Ответ

1 голос
/ 05 августа 2020

Буфер «буферизует» значения до своего размера, учитывая обратное давление в нисходящем направлении.

Таким образом, он обеспечивает разрыв (буфер?) Между тем, что отправляет восходящий поток, и тем, что нисходящий поток готов к принять. Timer просто отбрасывает значения, если нисходящий поток не готов принять, но Buffer готов к приему (до его возможностей с .keepFull, или всегда / неограниченно со стратегией предварительной выборки .byRequest )

В частности, в этом примере, если мы передаем значения из Timer напрямую, буфер примет все начальные результаты (начальные результаты будут с интервалом 0,2 мс c), прежде чем будут заполнены и установлены в установившееся состояние (2 сек c друг от друга).

Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
    .buffer(size: 4, prefetch: .keepFull, whenFull: .dropNewest)
    .flatMap(maxPublishers:.max(1)) {
        Just($0).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($0).delay(for: 2, scheduler: DispatchQueue.main) 
           }
           .sink { print($0) }

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

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

При этом мне не совсем понятно, что хороший вариант использования - .keepFull против .byRequest.

...