可观察的迭代完成事件

时间:2016-12-10 09:36:03

标签: javascript typescript rxjs observable rxjs5

我正在订阅发出一系列路线的 BehaviorSubject routes$

e.g。 ['left', 'top', 'left']

然后我想以200ms的延迟记录这个数组的每个元素,现在记录了所有元素之后,我想记录route finished

我尝试了完整的事件()=>{}finally()运算符,但由于routes$仍然存在并且可能会发出新的指示,因此它们都不会触发。

/** Stream recent directions */
this.route$.switchMap(() => {
  return Observable
    .interval(200)
    .timeInterval()
    .take(this.route$.getValue().length)
}).subscribe(
  (v) => {
    if (v.value === this.route$.getValue().length) return;
    let i = v.value;
    this.moveStep(this.route$.getValue()[i]);
  }
);

目前我正在使用此解决方法

.subscribe(
  (v) => {
    if (v.value === this.route$.getValue().length) return;
    let i = v.value;
    this.moveStep(this.route$.getValue()[i]);

    /** Check if it is the last iteration */
    if(i + 1 === this.route$.getValue().length){
      console.log('route finished');
      this.state = PlayerState.Idle;
    }
  }
);

是否有一种以可见的方式实现这一目标?

2 个答案:

答案 0 :(得分:3)

如果我理解你正在尝试做什么,你想要在传递给BehaviorSubject的数组完全迭代并且你想得到最后一个值时发出一个值。

尽量避免直接在Observable链中使用.getValue(),因为.getValue()的内容已经是您应该在链中使用的内容。

var routes$ = new BehaviorSubject(['default']);

routes$.switchMap((arr) => {
    return Observable.interval(200)
        .take(arr.length)
        .map(i => arr[i])
        .timeInterval()
        .do(null, null, () => console.log('Complete'));
}).subscribe(value => {
    console.log(value);
});

routes$.next(['left', 'top', 'left']);

setTimeout(() => {
    routes$.next(['top', 'right', 'down']);
}, 1000);

打印到控制台:

TimeInterval { value: 'left', interval: 208 }
TimeInterval { value: 'top', interval: 241 }
TimeInterval { value: 'left', interval: 207 }
Complete
TimeInterval { value: 'top', interval: 204 }
TimeInterval { value: 'right', interval: 200 }
TimeInterval { value: 'down', interval: 205 }
Complete

查看现场演示:https://jsbin.com/muxasa/5/edit?js,console

请注意,['default']永远不会重新发送,因为switchMap()在调用routes$.next(['left', 'top', 'left']);时会收到一个新数组

答案 1 :(得分:1)

如果您的Observable尚未完成,您可以使用debounce()等待一段时间后再做某事。其他选项是buffer您的值按时间/金额,然后在发出缓冲区后执行某些操作。