RxJs:如何根据可观察的状态进行循环

RxJs: How to loop based on state of the observable?

本文关键字:状态 循环 观察 何根 RxJs      更新时间:2023-09-26

我正试图让RxJs在流中的Observable上循环,直到它处于特定状态,然后让流继续。具体来说,我将同步do/while循环转换为RxJs,但我认为相同的答案也可以用于for或while循环。

我想我可以使用doWhile()来实现这一点,但条件函数似乎无法访问流中的项目,这似乎违背了我的目的。

我不完全确定我想要的正确反应术语是什么,但这里有一个我想要的例子:

var source = new Rx.Observable.of({val: 0, counter: 3});
source.map(o => {
  o.counter--;
  console.log('Counter: ' + o.counter);
  if (!o.counter) {
    o.val = "YESS!";
  }
  return o;
})
.doWhile(o => { 
  return o.counter > 0; 
})
.subscribe(
    function (x) {
        console.log('Next: ' + x.val);
    },
    function (err) {
        console.log('Error: ' + err);   
    },
    function () {
        console.log('Completed');   
    });

预期输出为:

Counter: 3
Counter: 2
Counter: 1
Counter: 0
Next: YESS!
Completed

假设这是一个可以解决的问题,我不清楚在循环时如何标记要返回的"开始"。

有一个expand运算符,它允许您递归调用选择器函数,从而使您关闭。在这种情况下,返回一个空的可观察对象将是您的休息。参见jsbin:

var source = Rx.Observable.return({val: 0, counter: 3})
    .expand(value =>  { 
      if(!value.counter) return Rx.Observable.empty();
      value.counter -= 1;
      if(!value.counter) value.val = 'YESS';
      return Rx.Observable.return(value)
    })
    .subscribe(value => console.log(value.counter ? 
                                    'Counter: ' + value.counter : 
                                    'Next: ' + value.val));

不是您想要的,而是使用expand运算符关闭,并用Rx.Observable.empty发出递归结束的信号(http://jsfiddle.net/naaycu71/3/):

var source = new Rx.Observable.of({val: 0, counter: 3});
source.expand(function(o) {
  console.log('Counter: ' + o.counter);
  o.counter--;
return (o.counter >= 0) ? Rx.Observable.just(o) : Rx.Observable.empty()
})
.subscribe(
    function (x) {
        console.log('Next: ' , x);
    },
    function (err) {
        console.log('Error: ' + err);   
    },
    function () {
        console.log('Completed');   
    });

输出:

Next:  Object {val: 0, counter: 3}
Counter: 3
Next:  Object {val: 0, counter: 2}
Counter: 2
Next:  Object {val: 0, counter: 1}
Counter: 1
Next:  Object {val: 0, counter: 0}
Counter: 0
Completed