问题
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