简体   繁体   English

如何根据每个元素的条件循环可观察序列?

[英]How can i loop the observable sequence based on condition from each element?

I have a sequence and i need to repeat it based on condition from each element. 我有一个序列,我需要根据每个元素的条件重复它。 For example i need to reprocess an element if it's marked with a "failed" flag. 例如,如果元素标有“失败”标志,我需要重新处理它。 My problem is i cannot find how to do the while-loop operation. 我的问题是我找不到如何进行while-loop操作。

TakeWhile is almost what i need but it does not repeat itself. TakeWhile几乎是我所需要的,但它不会重演。

/*
* The following lines are just an example to comprehend the idea
*/
var observableSequence = sequence.ToObservable();
observableSequence
    //This ´DoWhile´ did not worked because does not accept each element as argument
    //and sequence at this point is not the same as `observableSequence`
    .DoWhile(() => sequence.Any(item => !item.Failed))
    .Where(item => item.Failed == true) //OK here i could put another condition for limited retries...
    .Subscribe(item => {
        try{
            //Do stuff...
            //. . .
            item.Failed = false;
        } catch
        {
            item.Failed = true;
        }
    });

I'd suggest merging the original sequence with a new observable that you feed objects into as they fail. 我建议将原始序列与一个新的observable合并,以便在失败时将对象输入。

var retries = new ReplaySubject<Foo>();
var loopSequence = sequence.ToObservable().Merge(retries);

loopSequence
    .Where(item => item.Failed)
    .Subscribe(item =>
    {
        try{
            //Do stuff
            item.Failed = false;
        } catch
        {
            item.Failed = true;
        }
        retries.OnNext(item);
    });

It's generally considered bad practice to change state of objects in observables, so you might want to consider creating transforms instead: 在observables中更改对象状态通常被认为是不好的做法,因此您可能需要考虑创建转换:

loopSequence
    .Where(item => item.Failed)
    .Subscribe(item =>
    {
        try{
            //Do stuff
            retries.OnNext(new Item { ..., Failed = false });
        } catch
        {
            retries.OnNext(new Item { ..., Failed = true });
        }
    });

You should also be really careful with this pattern, since a continually-failing item will put your program execution into a kind of infinite loop. 你应该对这种模式非常小心,因为一个连续失败的项目会使你的程序执行成为一种无限循环。

You can wrap each value and retry the operations independently: 您可以包装每个值并独立重试操作:

observableSequence
  .SelectMany(item => 
    Observable.Return(item)
      .Select(x => //Do Stuff)
      //Optional argument, omitting retries infinitely until
      //success
      .Retry(3)
  )

  .Subscribe(item => {
    //Handle the results
  });

Optionally Return takes a IScheduler as its second argument which could change the order that retries get processed (recursive vs. trampoline). (可选) ReturnIScheduler作为其第二个参数,可以更改重试处理的顺序(递归与trampoline)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM