Как переадресовать отправленные вызовы от одного PassthroughSubject к другому (например, цепочка PassthroughSubject)? - PullRequest
0 голосов
/ 14 июля 2020

Представьте, что у меня есть API для класса, который использует PassthroughSubject для получения входных данных:

class Logger {
  let log: PassthroughSubject<String, Never>
}

Обычно я могу выдать значение, вызвав logger.log.send("test").

Теперь скажем, я хочу иметь свой собственный регистратор, который находится между этим общим c регистратором и моим кодом:

class MyLogger {
  let log: PassthroughSubject<String, Never>
}

Это должно быть префиксом строки, а затем отправлять любые обновления в Регистратор. Есть ли способ связать вывод одного объекта PassthroughSubject (например, MyLogger) с другим (например, Logger)?

Я знаю, что могу сделать это следующим образом:

let cancellable = myLogger.log.sink { 
  logger.log.send("[MyApp] " + $0)
}

Однако это не Это не похоже на способ объединения вещей в цепочку. Я надеялся, что есть API, более похожий на этот:

logger.log.subscribe(myLogger.log.map { "[MyApp] " + $0 })

Однако он не компилируется, поскольку я думаю, что карта заставляет его превращаться в издателя, а не в тему:

Метод экземпляра 'subscribe' требует, чтобы 'Publishers.Map , String> 'соответствует' Subject '

Есть ли более декларативный API для подписки одного PassthroughSubject на обновления от другого (с поддержкой промежуточных мутаций), помимо использования sink?

1 Ответ

0 голосов
/ 14 июля 2020

Если вы измените порядок подписки, это сработает:

let cancellable = myLogger.log
  .map { "[MyApp] " + $0 }
  .subscribe(logger.log)

myLogger.send("test") // will send "[MyApp] test" to logger.log

Сказав это, API-интерфейсы моделирования, подобные этому, с помощью Combine кажутся немного странными, а тип данных Failure кажется полностью игнорируется. Например, если журнал завершился неудачно, нет возможности восстановить цепочку, в которой произошел сбой.

Лучшим API может быть обычная функция, которая возвращает AnyPublisher:

class Logger {
  func log(_ string: String) -> AnyPublisher<Void, Never>
}

class MyLogger {
  func log(_ string: String) -> AnyPublisher<Void, Never> {
    return logger.log(string)
  }
}
...