Why/How 我应该在没有 Connect 的情况下使用 Publish 吗?

Why/How should I use Publish without Connect?

Why/how 我应该在没有 ConnectRefCount 调用的情况下使用 .Publish() 吗?它有什么作用?示例代码:

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));

Publish<TSource, TResult>(Func<IObservable<TSource, IObservable<TResult>> selector) 重载的文档很少。 Lee Campbell 没有在 introtorx.com 中介绍它。它不是 return 和 IConnectableObservable,这是大多数人联想到的 Publish,因此不需要或支持 ConnectRefCount 调用.

这种形式的 Publish 基本上是一种防御性编码形式,针对可观察源中可能出现的副作用。它订阅一次源,然后可以通过传入的参数安全地 'multicast' 所有消息。如果您查看问题代码,只有一次提到 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;
});

...你会发现 "Print me once" 一次用 pairs 打印(正确),两次用 pairs2 打印。这种效果具有类似的含义,您的可观察对象包装诸如数据库查询、Web 请求、网络调用、文件读取和其他您希望只发生一次而不是多次的副作用代码。

TL;DR: 如果您有一个两次引用一个可观察对象的可观察查询,最好将该可观察对象包装在一个 Publish 调用中。