У меня есть вопрос об операторе zip
в Combine в сочетании с противодавлением.
Возьмите следующий фрагмент кода:
let sequencePublisher = Publishers.Sequence<Range<Int>, Never>(sequence: 0..<Int.max)
let subject = PassthroughSubject<String, Never>()
let handle = subject
.zip(sequencePublisher.print())
.print()
.sink { letters, digits in
print(letters, digits)
}
subject.send("a")
При выполнении этого на детской площадке, следующий вывод:
receive subscription: (0..<9223372036854775807)
receive subscription: (Zip)
request unlimited
request unlimited
receive value: (0)
receive value: (1)
receive value: (2)
receive value: (3)
receive value: (4)
receive value: (5)
receive value: (6)
receive value: (7)
...
При выполнении его на устройстве iOS код падает через несколько секунд из-за проблем с памятью.
Основная причина видна в четвертая строка выше, где zip
запрашивает неограниченное количество значений из sequencePublisher
. Поскольку sequencePublisher
предоставляет весь диапазон значений Int
, это вызывает переполнение памяти.
Что я думаю знать:
zip
ожидает по одному значению каждого издатель, прежде чем объединить их и нажать на - противодавление, используется для контроля спроса от подписчика к издателю
Я ожидаю, что zip
запрашивает только одно значение от каждого издатель ожидает их поступления и запрашивает следующие значения, только когда получил одно от каждого.
В этом конкретном случае я попытался построить поведение, в котором порядковый номер присваивается каждому значению, которое создается subject
. Однако я могу себе представить, что это всегда проблема, когда zip
объединяет значения от издателей, которые публикуют sh с очень разными частотами.
Использование противодавления в операторе zip
кажется идеальным инструментом для решения этой проблемы. Вы знаете, почему это не так? Это ошибка или намеренная? Если намеренно, почему?
Спасибо, ребята