我目前正试图想出一种暂停观察的方法。在github https://github.com/ReactiveX/rxjs/issues/1542看到blesh的帖子后,我想我正走在正确的轨道上。但是由于某些原因,一旦我从我的暂停主题执行switchMap(),我的观察者上的takeWhile()就会被忽略。
这正确结束:
export class CompositionService {
cursor = -1;
pauser = new Subject();
interval;
init = (slides) => {
let waitUntil = 0;
return this.interval = Observable
.range(0, slides.length)
.mergeMap((i) => {
let next = Observable.of(i).delay(waitUntil);
waitUntil += !!slides[i]["duration"] ? slides[i]["duration"] : 0;
return next;
})
.scan((cursor) => {
return this.cursor = cursor = slides[cursor + 1] ? cursor + 1 : -1;
}, this.cursor)
.map(cursor => slides[cursor])
.takeWhile((slide) => {
return !!slide;
});
};
// these methods are not called for this sample
play = () => {
this.pauser.next(false);
};
pause = () => {
this.pauser.next(true);
};
};
以这种方式调用时可以正常工作:
it("should subscribe to init", (done) => {
slides.forEach((slide, i) => {
if (slide.duration) {
slide.duration = slide.duration / 100;
}
});
composition.init(slides).subscribe(
(slide) => {
console.log(slide);
},
(err) => {
console.log("Error: " + err);
},
() => {
done();
});
});
虽然上一个示例的工作方式与广告一样,但当我添加一些“魔术”时,Observer永远不会结束:
export class CompositionService2 {
cursor = -1;
pauser = new Subject();
interval;
init = (slides) => {
let waitUntil = 0;
this.interval = Observable
.range(0, slides.length)
.mergeMap((i) => {
let next = Observable.of(i).delay(waitUntil);
waitUntil += !!slides[i]["duration"] ? slides[i]["duration"] : 0;
return next;
})
.scan((cursor) => {
return this.cursor = cursor = slides[cursor + 1] ? cursor + 1 : -1;
}, this.cursor)
.map(cursor => slides[cursor])
.takeWhile((slide) => {
return !!slide;
});
return this.pauser
// leaving commented for clarity of the end game
// .switchMap( paused => paused ? Observable.never() : this.interval );
// however, not even a straight forward switchMap is yeilding the expected results
.switchMap( paused => this.interval );
};
play = () => {
this.pauser.next(false);
};
pause = () => {
this.pauser.next(true);
};
};
以这种方式打电话:
it("should subscribe to init", (done) => {
slides.forEach((slide, i) => {
if (slide.duration) {
slide.duration = slide.duration / 100;
}
});
composition.init(slides).subscribe(
(slide) => {
console.log(slide);
},
(err) => {
console.log("Error: " + err);
},
() => {
//I never get here!!!!!
done();
});
// kickstart my heart!
composition.play();
});
任何人都有任何想法我在这里做错了吗?
答案 0 :(得分:1)
您没有完成外部流。在takeWhile
完成流的第一个版本中,您将完成。但是,一旦你将其嵌套在switchMap
内。您只是在完成内部流,因为外部流(a Subject
)永远不会完成。当它被展平时,它对用户来说似乎是一个永无止境的流。
如果要完成它,则需要在某个时刻终止流,例如:
composition.init(slides)
.take(3)
.subscribe(
(slide) => {
console.log(slide);
},
(err) => {
console.log("Error: " + err);
},
() => {
//I never get here!!!!!
done();
});
我不是非常相信Rx实际上是正确的工具,因为流不是真正设计为“暂停”,因为你实际上无法阻止Observable继续传播。您可能已经注意到在暂停之间跳转到存储状态的箍数,因此考虑使用生成器或其他库(如IxJS
)可能是有意义的。但我离题了。