可观察迭代完成事件
Observable iteration complete event
我正在订阅一个 BehaviorSubject routes$
发出方向数组
例如['left', 'top', 'left']
然后我想以 200 毫秒的延迟记录这个数组的每个元素,现在在记录所有元素之后,我想记录 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;
}
}
);
在 observable 中是否有本地方法来实现这一点?
如果我理解正确,你想在传递给 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']);
时收到一个新数组
如果您的 Observable 尚未完成,您可以使用 debounce()
等待一定时间后再做某事。其他选择是通过 time/amount buffer
你的值,然后在发出缓冲区后做一些事情。
我正在订阅一个 BehaviorSubject routes$
发出方向数组
例如['left', 'top', 'left']
然后我想以 200 毫秒的延迟记录这个数组的每个元素,现在在记录所有元素之后,我想记录 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;
}
}
);
在 observable 中是否有本地方法来实现这一点?
如果我理解正确,你想在传递给 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']);
如果您的 Observable 尚未完成,您可以使用 debounce()
等待一定时间后再做某事。其他选择是通过 time/amount buffer
你的值,然后在发出缓冲区后做一些事情。