Я создал цепочку издателей Combine, которая выглядит примерно так:
let pub = getSomeAsyncData()
.mapError { ... }
.map { ... }
...
.flatMap { data in
let wsi = WebSocketInteraction(data, ...)
return wsi.subject
}
.share().eraseToAnyPublisher()
Это поток различных возможных сетевых запросов и преобразований данных. Вызывающий код хочет подписаться на pub
, чтобы узнать, когда весь асинхронный процесс завершился успешно или потерпел неудачу.
Меня смущает конструкция шага flatMap
с WebSocketInteraction
. Я написал это вспомогательный класс. Я не думаю, что его внутренние детали важны, но его цель - предоставить свойство subject
(a PassthroughSubject
) в качестве следующего издателя в цепочке. Внутренне WebSocketInteraction
использует URLSessionWebSocketTask
, общается с сервером и публикует на subject
. Мне нравится flatMap
, но как сохранить этот фрагмент в течение всего срока существования цепочки Publisher?
Если я сохраню его во внешнем объекте (без проблем), то мне нужно его очистить. Я мог бы сделать , что , когда subject
завершится, но если вызывающий отменит всю цепочку издателя, я не получу событие завершения. Нужно ли мне использовать Publisher.handleEvents
и также ожидать отмены? Это кажется немного некрасивым. Но, может быть, другого пути нет ...
.flatMap { data in
let wsi = WebSocketInteraction(data, ...)
self.currentWsi = wsi // store in containing object to keep it alive.
wsi.subject.sink(receiveCompletion: { self.currentWsi = nil })
wsi.subject.handleEvents(receiveCancel: {
wsi.closeWebSocket()
self.currentWsi = nil
})
У кого-нибудь есть здесь хорошие «шаблоны проектирования»? Например, вместо WebSocketInteraction
vend a PassthroughSubject
он может соответствовать Publisher
. Я могу пойти по этому пути, но создание собственного Combine Publisher
- это больше работы, а документация побуждает людей использовать вместо этого предмет. Чтобы создать настраиваемого издателя, вам необходимо реализовать некоторые из вещей, которые PassthroughSubject
делает за вас, например, реагирование на запрос и отмену, а также сохранение состояния, чтобы гарантировать, что вы завершите работу не более одного раза и не отправите события после этого.
[Изменить: чтобы уточнить, что WebSocketInteraction
- мой собственный класс.]