Issue
In Angular (v12) I've got the component you can see below:
component.html
<h3 *ngIf="userInfo$ | async as userInfo; else loading">{{ userInfo.user.name }}</h3>
<ng-template #loading>
Loading...
</ng-template>
component.ts
token: string;
userInfo$: Observable<any>
getUserInfo: Subject<string> = new Subject<string>()
constructor(
private service: Service,
private route: ActivatedRoute
) { }
ngOnInit(): void {
this.userInfo$ = this.getUserInfo.pipe(
mergeMap(token => {
return this.service.getKey(token).pipe(
map(res => {
return {
user: res.client,
info: res.info
}
})
);
}),
tap((res) => console.log(res))
)
this.route.paramMap.subscribe(params => {
this.token = params.get("token");
this.getUserInfo.next(this.token);
});
}
Using the async pipe the user'll get a perpetual loading, while if I this.getUserInfo.pipe(..).subscribe() the right response is logged.
I know that the async pipe subscribes and unsubscribes to the observables, so I expected the ngIf to be truthful.
Solution
You have an issue with timing. The problem is that this.getUserInfo.next(this.token) emits before the async pipe subscribes, so you don't receive the emission.
You can simplify your observable chain a bit which would side-step this timing issue.
@Component(...)
class MyComponent() {
private token$ = this.route.paramMap.pipe(
map(params => params.get('token')),
distinctUntilChanged()
);
userInfo$ = this.token$.pipe(
switchMap(token => this.service.getKey(token)),
map(res => ({
user: res.client,
info: res.info
}))
);
constructor(
private service: Service,
private route: ActivatedRoute
) { }
}
Notice the token is defined as an observable and we defined userInfo$ as an observable that depends on the token$ emissions. There's no need for a separate Subject and a subscription. We also don't need to use ngOnInit.
Answered By - BizzyBob
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.