2016-12-16 59 views
0

我刚刚开始讨论反应式编程,并且我知道编写代码就足够了,但当我没有得到我期望的结果时,我不知道发生了什么。除博客帖子外,我没有真正的导师。我还没有找到一个很好的解决方案来解决我遇到的情况,我对正确的方法感到好奇。我如何使用无功编程编写此代码?

问题:

我需要得到一个富,这是部分地由酒吧对象的数组的。我从Web服务中获取Bar对象。因此,我将每个Web服务调用都表示为IObservable,在完成之前,我预计会有0或1个元素。我想创建一个IObservable:

  • 订阅每个IObservable实例。
  • 等待最多2秒超时。
  • 当任两个序列完成或超时发生的情况:
    • 创建与任何中生成的酒吧对象数组(可能有0)
    • 使用酒吧[]产生Foo对象。

我有点与此位的代码来实现这一点:

public Foo CreateFoo() { 

     var producer1 = webService.BarGenerator() 
            .Timeout(TimeSpan.FromSeconds(2), Observable.Empty<Bar>()); 
     var producer2 = // similar to above 

     var pipe = producer1.Concat(producer2); 

     Bar[] result = pipe.ToEnumerable().ToArray(); 

     ... 
} 

这看起来不正确,对于很多的原因。最明显的是Concat()将串行启动序列而不是并行,所以这是一个4秒的超时。我并不在乎它会阻塞,它对于我正在使用的架构来说确实很方便。我很好用这种方法成为的IObservable的发电机,但在这里,似乎让这具有挑战性的一些额外的警告当我尝试:

  1. 我需要的最后一个数组把producer1和producer2的结果的顺序,如果他们都产生结果。
  2. 我想使用TestScheduler来验证超时但尚未成功,但我显然根本不理解调度程序。
  3. 这最终是一个拉式模型,无论得到Foo在某个特定的时刻需要它,并且没有任何价值可以“随时”接收它。也许这就是“不使用Rx”的答案。说实话,我被卡住了,我切换到基于任务的API。但我想看看如何用Rx来解决这个问题,因为我想学习。
+0

我感到那邮编将是一个更适合您的问题比的毗连。 –

+0

@EricLippert:嗯......我不得不做一些工作,以确保我在事后得到了正确的顺序,但我确实看到了这可能会更好。 – OwenP

+0

为什么很难让他们顺利? 'firstBars.Zip(secondBars,(first,second)=> new {first,second}',现在你可以观察到{first,second}对。 –

回答

0
var pipe = producer1 
     .Merge(producer2) 
     .Buffer(Observable.Timer(TimeSpan.FromSeconds(2), testScheduler)) 
     .Take(1); 

    var subscription = pipe 
     .Select(list => new Foo(list.ToArray()) 
     .Subscribe(foo => {} /* Do whatever you want with your foo here.*/); 

Buffer需要(在两秒钟在我们的情况下)一个窗口期间发射的所有元素,并输出一个列表。

如果要坚持你的拉模型,而不是订阅的,你可以这样做:

var list = await pipe; 
var foo = new Foo(list.ToArray()); 

//.... 
+0

这看起来应该起作用,并且与测试调度程序一起工作。为了完成排序,我创建了一个类,让我可以将整数“排序顺序”添加到任何给定的值。然后,在最后的阶段,我排序该枚举并将其转换回字符串序列。 – OwenP