Making one observable after the other one is complete

时间秒杀一切 提交于 2020-03-04 20:01:21

问题


I subscribe to observable below:

    this.router.events
        .filter(event => event instanceof NavigationEnd)
        .startWith({})
        .pairwise()
        .subscribe((events: [NavigationEnd, NavigationEnd]) => {
            if (
                this.breadcrumbs.length > 0 &&
                events[0].url &&
                events[0].url.split("?")[0] === events[1].url.split("?")[0]
            ) {
                return;
            }
            let root: ActivatedRoute = this.activatedRoute.root;
            this.breadcrumbs = this.getBreadcrumbs(root);

            this.checkSetIsHomePage();
            this.setBreadcrumbHeight();
        });

and I want to subscribe to observable below when the top one is done:

    this.breadcrumbService.additionalBreadcrumbs
        .takeUntil(this.destroy$)
        .subscribe(breadcrumb => {
            if (breadcrumb.index) {
                this.breadcrumbs.splice(breadcrumb.index, 0, breadcrumb);
            } else {
                this.breadcrumbs.push(breadcrumb);
            }

            this.setBreadcrumbHeight();
        });

these are two separate observable, I used delay but I know its not the best practice to do that, how would you suggest to do it?


回答1:


You shouldn't subscribe to the first observable, but instead use one more operator to finally subscribe to the second observable. The operator you want is either mergemap or switchmap.

EDIT

Could you try this ?

this.router.events
    .filter(event => event instanceof NavigationEnd)
    .startWith({})
    .pairwise()
    .tap((events: [NavigationEnd, NavigationEnd]) => {
        if (
            this.breadcrumbs.length > 0 &&
            events[0].url &&
            events[0].url.split("?")[0] === events[1].url.split("?")[0]
        ) {
            return;
        }
        let root: ActivatedRoute = this.activatedRoute.root;
        this.breadcrumbs = this.getBreadcrumbs(root);

        this.checkSetIsHomePage();
        this.setBreadcrumbHeight();
    })
    .switchMap(() => this.breadcrumbService.additionalBreadcrumbs)
    .takeUntil(this.destroy$)
    .subscribe(breadcrumb => {
        if (breadcrumb.index) {
            this.breadcrumbs.splice(breadcrumb.index, 0, breadcrumb);
        } else {
            this.breadcrumbs.push(breadcrumb);
        }

        this.setBreadcrumbHeight();
    });

What you do here is use the tap operator to manipulate your "this" on each emit, but you don't change the observable and you don't emit one yourself. Then you switch to the second observable, on each emit of the first.




回答2:


I would say that the operator that you need at RXJS is concat

Instead of subscribing directly to both Observables, you may need to pipe them with a map to perform the operation needed and finally concat them.

const observable1 = this.router.events
        .filter(event => event instanceof NavigationEnd)
        .startWith({})
        .pairwise()
        .pipe(map((events: [NavigationEnd, NavigationEnd]) => {
            if (
                this.breadcrumbs.length > 0 &&
                events[0].url &&
                events[0].url.split("?")[0] === events[1].url.split("?")[0]
            ) {
                return;
            }
            let root: ActivatedRoute = this.activatedRoute.root;
            this.breadcrumbs = this.getBreadcrumbs(root);

            this.checkSetIsHomePage();
            this.setBreadcrumbHeight();
        }));

const observable2 =     this.breadcrumbService.additionalBreadcrumbs
        .takeUntil(this.destroy$)
        .pipe(map(breadcrumb => {
            if (breadcrumb.index) {
                this.breadcrumbs.splice(breadcrumb.index, 0, breadcrumb);
            } else {
                this.breadcrumbs.push(breadcrumb);
            }

            this.setBreadcrumbHeight();
        });

concat(observable1,observable2).subscribe()

I haven't test it but I think it should work




回答3:


you can use finalize

this.router.events
    .filter(event => event instanceof NavigationEnd)
    .startWith({})
    .pairwise()
    .pipe(
        finalize(() => {

            this.breadcrumbService.additionalBreadcrumbs
                .takeUntil(this.destroy$)
                .subscribe(breadcrumb => {
                    if (breadcrumb.index) {
                        this.breadcrumbs.splice(breadcrumb.index, 0, breadcrumb);
                    } else {
                        this.breadcrumbs.push(breadcrumb);
                    }

                    this.setBreadcrumbHeight();
                });
        })
    )
    .subscribe((events: [NavigationEnd, NavigationEnd]) => {
        if (
            this.breadcrumbs.length > 0 &&
            events[0].url &&
            events[0].url.split("?")[0] === events[1].url.split("?")[0]
        ) {
            return;
        }
        let root: ActivatedRoute = this.activatedRoute.root;
        this.breadcrumbs = this.getBreadcrumbs(root);

        this.checkSetIsHomePage();
        this.setBreadcrumbHeight();
    });


来源:https://stackoverflow.com/questions/60344904/making-one-observable-after-the-other-one-is-complete

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!