Почему / Как я должен использовать Публикация без Connect? - PullRequest
0 голосов
/ 12 декабря 2018

Почему / как я должен использовать .Publish() без вызова Connect или RefCount?Что оно делает?Пример кода:

var source = new Subject<int>();

var pairs = source.Publish(_source => _source
    .Skip(1)
    .Zip(_source, (newer, older) => (older, newer))
);

pairs.Subscribe(p => Console.WriteLine(p));

source.OnNext(1);
source.OnNext(2);
source.OnNext(3);
source.OnNext(4);

Чем pairs отличается от pairs2 здесь:

var pairs2 = source
    .Skip(1)
    .Zip(source, (newer, older) => (older, newer));

1 Ответ

0 голосов
/ 12 декабря 2018

Перегрузка Publish<TSource, TResult>(Func<IObservable<TSource, IObservable<TResult>> selector) плохо документирована.Ли Кэмпбелл не покрывает это в introtorx.com .Он не возвращает IConnectableObservable, то есть то, что большинство людей ассоциирует с Publish, и поэтому не требует или не поддерживает Connect или RefCount вызов.

Эта форма Publish в основном является формой защитного кодирования от возможных побочных эффектов в наблюдаемом источнике.Он подписывается один раз на источник, а затем может безопасно «рассылать» все сообщения через переданный параметр.Если вы посмотрите на код вопроса, там только один раз упоминается source и два упоминания _source._source здесь - безопасная многоадресная наблюдаемая, source - небезопасная.

В приведенном выше примере источник - это простой Subject, поэтому он не является на самом деле небезопасным, и поэтому Publish имеетнет эффекта.Однако, если вы замените source на это:

var source = Observable.Create<int>(o =>
{
    Console.WriteLine("Print me once");
    o.OnNext(1);
    o.OnNext(2);
    o.OnNext(3);
    o.OnNext(4);
    return System.Reactive.Disposables.Disposable.Empty;
});

... вы обнаружите, что «Напечатать меня один раз» напечатано один раз с pairs (правильно) и дважды с pairs2.Этот эффект имеет аналогичные последствия, когда ваша наблюдаемая оболочка включает в себя такие вещи, как запросы к БД, веб-запросы, сетевые вызовы, чтение файлов и другой побочный код, который вы хотите выполнить только один раз, а не несколько раз.

TL; DR: Если у вас есть наблюдаемый запрос, который дважды ссылается на наблюдаемый, лучше всего обернуть этот наблюдаемый в вызов Publish.

...