反应:试图了解受试对象; T>工作 [英] Reactive: Trying to understand how Subject<T> work

查看:144
本文介绍了反应:试图了解受试对象; T>工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图了解如何使用受试对象; T> ReplaySubject< T> 等工作。下面是例子:



(主题是可观的观察者)

 公开的IObservable< INT> CreateObservable()
{
受试对象; INT> SUBJ =新的受试对象;诠释>(); //情况1
ReplaySubject< INT> SUBJ =新ReplaySubject<&诠释GT;(); //情况下2

随机RND =新的随机();
INT maxValue分别= rnd.Next(20);
Trace.TraceInformation(最大的价值是:+ maxValue.ToString());

subj.OnNext(-1); //特定值

为(INT iCounter = 0; iCounter<包括maxValue; iCounter ++)
{
Trace.TraceInformation(值:+ iCounter.ToString()+ 即将发布);
subj.OnNext(iCounter);
}

Trace.TraceInformation(发布完成);
subj.OnComplete();

返回SUBJ;
}

公共无效的主要()
{
//
//第一个收费
CreateObservable()
.Subscribe (
onNext:(X)= GT; {
Trace.TraceInformation(X为:+ x.ToString());
});

//
//第二认购
CreateObservable()
.Subscribe(
onNext:(×2)=> {
跟踪.TraceInformation(X 2是:+ x.ToString());
});



案例1:奇怪的情况是 - 当我使用受试对象; T> 没有订阅时(???) - 我从来没有看到的X是:文字 - 我只看到了值是:和最大值是......为什么受试对象; T> 不压值订阅



案例2:如果我使用 ReplaySubject< ; T> - 我确实看到订阅的值,但我不能适用推迟选项任何东西。不要主题,而不是观测....所以每认购将获得不同的值,因为 CreateObservable 函数的的观测。哪里是推迟


解决方案

您需要铭记,当代码被执行



在案例1,当您使用受试对象; T> ,你会发现该所有呼叫到 OnNext &安培;前观察到的 OnCompleted 完成由 CreateObservable 方法返回。由于您使用的是受试对象; T> 这意味着任何后续订阅将错过所有的值,所以你应该希望得到你得到了什么 - 没有什么。

您不得不推迟关于这个问题的操作,直到你有订阅的观察者。要做到这一点使用创建方法。具体方法如下:

 公开的IObservable< INT> CreateObservable()
{
返回Observable.Create< INT>(O =>
{
变种SUBJ =新的受试对象; INT>();
无功弃= subj.Subscribe(O);

变种RND =新的随机();
变种包括maxValue = rnd.Next(20);
subj.OnNext(-1);
为(INT iCounter = 0; iCounter<包括maxValue; iCounter ++)
{
subj.OnNext(iCounter);
}
subj.OnCompleted();

返回支配;
});
}



我已经删除了所有的跟踪代码简洁。



所以,现在,对于每一个用户,你进去代码的一个新的执行创建方法和你现在会从获取值内部受试对象; T>



使用的创建方法通常是创建从方法返回观测的正确方法



另外,您可以使用 ReplaySubject< T> 并避免使用创建的方法。然而,这是不具吸引力的多种原因。它迫使整个序列的创建时间计算。这给你一个寒冷的观察到的,你本来可以更有效地生产,而无需使用重播主题。



现在,顺便说一句,你应该尽量避免使用对象的。一般的规则是,如果你使用一个主题,那么你正在做的事情是错误的。在 CreateObservable 方法将被更好地写成这样:

 公开的IObservable< INT> CreateObservable()
{
返回Observable.Create< INT>(O =>
{
变种RND =新的随机();
变种包括maxValue = RND。下一页(20);
返回Observable.Range(-1,包括maxValue + 1).Subscribe(O);
});
}

没有必要的对象都没有。



让我知道,如果这有助于。


Trying to understand how the Subject<T>, ReplaySubject<T> and other work. Here is example:

(Subject is Observable and observer)

public IObservable<int> CreateObservable()
{
     Subject<int> subj = new Subject<int>();                // case 1
     ReplaySubject<int> subj = new ReplaySubject<int>();    // case 2

     Random rnd = new Random();
     int maxValue = rnd.Next(20);
     Trace.TraceInformation("Max value is: " + maxValue.ToString());

     subj.OnNext(-1);           // specific value

     for(int iCounter = 0; iCounter < maxValue; iCounter++)
     {
          Trace.TraceInformation("Value: " + iCounter.ToString() + " is about to publish");
          subj.OnNext(iCounter);
      }

      Trace.TraceInformation("Publish complete");
      subj.OnComplete();

      return subj;
 }

 public void Main()
 {
     //
     // First subscription
     CreateObservable()
         .Subscribe(
               onNext: (x)=>{  
                  Trace.TraceInformation("X is: " + x.ToString()); 
      });

     //
     // Second subscribe
     CreateObservable()
         .Subscribe(
               onNext: (x2)=>{  
                  Trace.TraceInformation("X2 is: " + x.ToString());
     });

Case 1: The strange situation is - when I use Subject<T> no subscription is made (???) - I never see the "X is: " text - I only see the "Value is: " and "Max value is"... Why does Subject<T> does not push values to subscription ?

Case 2: If I use ReplaySubject<T> - I do see the values in Subscription but I could not apply Defer option to anything. Not to Subject and not to Observable.... So every subscription will receive different values because CreateObservable function is cold observable. Where is Defer ?

解决方案

You need to be mindful of when code is executed.

In "Case 1", when you use a Subject<T>, you'll notice that the all of the calls to OnNext & OnCompleted finish before the observable is returned by the CreateObservable method. Since you are using a Subject<T> this means that any subsequent subscription will have missed all of the values so you should expect to get what you got - nothing.

You have to delay the operations on the subject until you have the observer subscribed. To do that using the Create method. Here's how:

public IObservable<int> CreateObservable()
{
    return Observable.Create<int>(o =>
    {
        var subj = new Subject<int>();
        var disposable = subj.Subscribe(o);

        var rnd = new Random();
        var maxValue = rnd.Next(20);
        subj.OnNext(-1);
        for(int iCounter = 0; iCounter < maxValue; iCounter++)
        {
            subj.OnNext(iCounter);
        }
        subj.OnCompleted();

        return disposable;
    });
}

I've removed all the trace code for succinctness.

So now, for every subscriber, you get a new execution of the code inside the Create method and you would now get the values from the internal Subject<T>.

The use of the Create method is generally the correct way to create observables that you return from methods.

Alternatively you could use a ReplaySubject<T> and avoid the use of the Create method. However this is unattractive for a number of reasons. It forces the computation of the entire sequence at creation time. This give you a cold observable that you could have produced more efficiently without using a replay subject.

Now, as an aside, you should try to avoid using subjects at all. The general rule is that if you're using a subject then you're doing something wrong. The CreateObservable method would be better written as this:

public IObservable<int> CreateObservable()
{
    return Observable.Create<int>(o =>
    {
        var rnd = new Random();
        var maxValue = rnd.Next(20);
        return Observable.Range(-1, maxValue + 1).Subscribe(o);
    });
}

No need for a subject at all.

Let me know if this helps.

这篇关于反应:试图了解受试对象; T&GT;工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆