Angular 订阅外数据未定义
Angular data undefined outside subscribe
我知道它被问了一百万次,但我真的不明白它是如何工作的。我尝试了新的 Promise,但里面什么都没有 then()
我试图用 mergeMap 来做,但搞砸了。
我想获得当前用户最喜欢的项目。为此,我调用了这个方法:
user: IUser;
tracks: ITrack[] = [];
public getFavorites() {
this.userService.getFavourite(this.user.id).subscribe(
(tracks: ILike[]) => {
if (tracks) {
tracks.forEach(track => {
this.tracks.push(this.loadTracks(track.id));
});
}
}
);
对于这种方法,我需要我得到的用户 ID 和 :
private async loadUser() {
this.accountService.currentUser$.subscribe((user: IUser) => {
// getting into another service, because currentUser don't have id
this.userService.getUserByUsername(user.username).subscribe((u: IUser) => {
this.user = u;
})
})
}
还有 track_id:
loadTracks(id: number) {
let track: ITrack;
this.trackService.getTrack(id).subscribe(t => track = t);
return track;
}
ngOnInit():
this.loadUser();
this.getFavorites();
如何正确使用 mergeMap?
我想你会想在这种情况下使用 switchMap
。
this.accountService.currentUser$.pipe(
switchMap((user: IUser)=> {
return this.userService.getUserByUsername(user.username);
}),
tap(user => {
console.log(user); // Check if its work
}),
switchMap(user => {
return this.userService.getFavourite(this.user.id)
}),
tap(tracks => {
console.log(tracks); // Now you have track
})
); // You can .subscribe() here or use async pipe
您也可以拆分此逻辑并重复使用
const getUser$ = this.accountService.currentUser$.pipe(
switchMap((user: IUser)=> {
return this.userService.getUserByUsername(user.username);
})
);
阅读更多关于高阶可观察量的信息here
您可能正在寻找 switchMap
而不是 mergeMap
。 mergeMap
当你想合并 observables 的结果时应该使用。
这是一个工作示例:
https://stackblitz.com/edit/typescript-sdf2gy?file=index.ts
let userLocation$ = of({ userId: 123 }).pipe(delay(2000));
let getFavourite = function (userId) {
return of({ someData: 'someData: ' + userId }).pipe(delay(1000));
};
userLocation$
.pipe(switchMap((data) => getFavourite(data.userId)))
.subscribe((v) => console.log(v));
如果将所有内容都保持为可观察的,您可能会发现更容易理解(直到您确实需要订阅)。我们可以将每条数据声明为一个可观察源,然后从另一个定义一个可观察到的。
user$: Observable<IUser> = this.accountService.currentUser$.pipe(
switchMap(user => this.userService.getUserByUsername(user.username))
);
tracks$: Observable<ITrack[]> = this.user$.pipe(
switchMap(user => this.userService.getFavourite(user.id)),
switchMap(tracks => forkJoin(
tracks.map(t => this.trackService.getTrack(t.id))
))
);
现在,只需订阅 tracks$
即可获取曲目列表。不需要额外的变量来存储数据,不需要调用“加载”方法,甚至不需要使用 ngOnit
.
注意 tracks$
的定义是如何以 user$
开头的。这清楚地表明,当 user$
发出新值(accountService.currentUser$
更改 )时,tracks$
将自动发出更新的曲目列表。
注意:您可能会发现 有帮助,因为问题涉及类似的情况并且答案有非常 in-depth 的解释。
我知道它被问了一百万次,但我真的不明白它是如何工作的。我尝试了新的 Promise,但里面什么都没有 then()
我试图用 mergeMap 来做,但搞砸了。
我想获得当前用户最喜欢的项目。为此,我调用了这个方法:
user: IUser;
tracks: ITrack[] = [];
public getFavorites() {
this.userService.getFavourite(this.user.id).subscribe(
(tracks: ILike[]) => {
if (tracks) {
tracks.forEach(track => {
this.tracks.push(this.loadTracks(track.id));
});
}
}
);
对于这种方法,我需要我得到的用户 ID 和 :
private async loadUser() {
this.accountService.currentUser$.subscribe((user: IUser) => {
// getting into another service, because currentUser don't have id
this.userService.getUserByUsername(user.username).subscribe((u: IUser) => {
this.user = u;
})
})
}
还有 track_id:
loadTracks(id: number) {
let track: ITrack;
this.trackService.getTrack(id).subscribe(t => track = t);
return track;
}
ngOnInit():
this.loadUser();
this.getFavorites();
如何正确使用 mergeMap?
我想你会想在这种情况下使用 switchMap
。
this.accountService.currentUser$.pipe(
switchMap((user: IUser)=> {
return this.userService.getUserByUsername(user.username);
}),
tap(user => {
console.log(user); // Check if its work
}),
switchMap(user => {
return this.userService.getFavourite(this.user.id)
}),
tap(tracks => {
console.log(tracks); // Now you have track
})
); // You can .subscribe() here or use async pipe
您也可以拆分此逻辑并重复使用
const getUser$ = this.accountService.currentUser$.pipe(
switchMap((user: IUser)=> {
return this.userService.getUserByUsername(user.username);
})
);
阅读更多关于高阶可观察量的信息here
您可能正在寻找 switchMap
而不是 mergeMap
。 mergeMap
当你想合并 observables 的结果时应该使用。
这是一个工作示例: https://stackblitz.com/edit/typescript-sdf2gy?file=index.ts
let userLocation$ = of({ userId: 123 }).pipe(delay(2000));
let getFavourite = function (userId) {
return of({ someData: 'someData: ' + userId }).pipe(delay(1000));
};
userLocation$
.pipe(switchMap((data) => getFavourite(data.userId)))
.subscribe((v) => console.log(v));
如果将所有内容都保持为可观察的,您可能会发现更容易理解(直到您确实需要订阅)。我们可以将每条数据声明为一个可观察源,然后从另一个定义一个可观察到的。
user$: Observable<IUser> = this.accountService.currentUser$.pipe(
switchMap(user => this.userService.getUserByUsername(user.username))
);
tracks$: Observable<ITrack[]> = this.user$.pipe(
switchMap(user => this.userService.getFavourite(user.id)),
switchMap(tracks => forkJoin(
tracks.map(t => this.trackService.getTrack(t.id))
))
);
现在,只需订阅 tracks$
即可获取曲目列表。不需要额外的变量来存储数据,不需要调用“加载”方法,甚至不需要使用 ngOnit
.
注意 tracks$
的定义是如何以 user$
开头的。这清楚地表明,当 user$
发出新值(accountService.currentUser$
更改 )时,tracks$
将自动发出更新的曲目列表。
注意:您可能会发现