Javascript 对主题使用mergeMap()会忽略我正在合并的可观察对象上的takeWhile()

Javascript 对主题使用mergeMap()会忽略我正在合并的可观察对象上的takeWhile(),javascript,typescript,rxjs,Javascript,Typescript,Rxjs,我目前正试图找出一种方法来暂停一个可观察到的事件。在看过blesh在github上的帖子后,我认为我的思路是正确的。但是由于某种原因,一旦我从pauser主题执行到它的switchMap(),我的观察者上的takeWhile()就会被忽略 这正确地结束了: export class CompositionService { cursor = -1; pauser = new Subject(); interval; init = (slides) => {

我目前正试图找出一种方法来暂停一个可观察到的事件。在看过blesh在github上的帖子后,我认为我的思路是正确的。但是由于某种原因,一旦我从pauser主题执行到它的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();
        });
});
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();
});
虽然上一个示例如广告所示,但当我添加一些“魔力”时,间隔观察者永远不会结束:

这样称呼:

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();
        });
});
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();
});

有人知道我做错了什么吗?

你没有完成外部流程。在第一个版本中,当
takeWhile
完成流时,您正在完成。但是,一旦您将其嵌套在
开关映射中
。您只完成了内部流,因为外部流(主题)永远不会完成。当这是平坦的,它似乎是一个永无止境的流的订户

如果要完成,需要在某个点终止流,例如:

composition.init(slides)
  .take(3)
  .subscribe(
    (slide) => {
        console.log(slide);
    },
    (err) => {
        console.log("Error: " + err);
    },
    () => {
        //I never get here!!!!!
        done();
    });
我不太相信Rx实际上是正确的工具,因为流并不是真正被设计为“暂停”,因为你实际上无法阻止可观察到的继续传播。您可能已经注意到,您跳过的箍数在暂停之间存储状态,因此考虑使用生成器或其他库可能是有意义的。但我离题了