识别 mergeMap 中的最后一个对象
identify last object within mergeMap
我想将我的排名实体与我在 ionic4/angular7 中的成员实体合并。
我实际做的是:
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => {
ranking.forEach(rank => {
this.membersService.get(rank.key).subscribe(member => {
rank.firstName = member.firstName;
rank.lastName = member.lastName;
rank.keyName = member.key;
})
});
return ranking;
}),
).subscribe((merged) => {
let ranking = merged as RankingModelAll;
this.rankingmodel.push(ranking);
//***
//CAN'T BE CORRECT HERE :( i only want to sort at last and also set the preloadingDone at Last
this.rankingmodel = this.rankingmodel.sort((n1,n2) => {
if(n1.points < n2.points) {
return 1;
}
if(n1.points > n2.points) {
return -1;
}
return 0;
});
this.preloadingDone = true;
// ****
});
将我的成员名称合并到排名模型中,但我如何识别合并实体的最后一个 运行 以将我的 preloadingDone 标志设置为 true 并进行最高排名排序?
合并映射中的 return 值应该是可观察的。在上面的代码中,排名将在订阅完成之前 returned,因此它将使用尚未更新的排名数据。
我想你想要的可能是这样的:
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => {
// an array of all observables which will return the merged rank and member data
const ranksWithMembers = ranking.map(rank=>{
return this.memberService.get(rank.key).pipe(
map(member=>{
return {
...rank,
firstName: member.firstName,
lastName: member.lastName,
keyName: member.key,
}
})
)
})
// does not emit until all observables in array emit. Emits all results.
return forkJoin(ranksWithMembers)
}),
).subscribe(...)
我对你的代码没什么意见。
- 嵌套订阅不是很好的做法。你应该把它弄平。
- 使用
subscribe(next, error, complete)
complete 处理程序将标志预加载完成设置为完成
- 在你的情况下,我会使用插入到已排序的数组中,而不是在最后对整个数组进行排序。
看看下面的片段:
const orderedInsert = compareFn => (array, item) => {/** need to code this :( */};
const insetRank = orderedInsert((n1,n2) => {
// your compare fn
if(n1.points < n2.points) {
return 1;
}
if(n1.points > n2.points) {
return -1;
}
return 0;
}
);
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => from(ranking))
mergeMap(rank =>this.membersService.get(rank.key).pipe(map(member => ({
...rank,
...member
}))
).subscribe((rankMerged:RankingModelAll) =>
insetRank(this.rankingmodel, rankMerged),
e => console.log(e),
() => {
this.preloadingDone = true;
console.log('Done')
});
我想将我的排名实体与我在 ionic4/angular7 中的成员实体合并。
我实际做的是:
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => {
ranking.forEach(rank => {
this.membersService.get(rank.key).subscribe(member => {
rank.firstName = member.firstName;
rank.lastName = member.lastName;
rank.keyName = member.key;
})
});
return ranking;
}),
).subscribe((merged) => {
let ranking = merged as RankingModelAll;
this.rankingmodel.push(ranking);
//***
//CAN'T BE CORRECT HERE :( i only want to sort at last and also set the preloadingDone at Last
this.rankingmodel = this.rankingmodel.sort((n1,n2) => {
if(n1.points < n2.points) {
return 1;
}
if(n1.points > n2.points) {
return -1;
}
return 0;
});
this.preloadingDone = true;
// ****
});
将我的成员名称合并到排名模型中,但我如何识别合并实体的最后一个 运行 以将我的 preloadingDone 标志设置为 true 并进行最高排名排序?
合并映射中的 return 值应该是可观察的。在上面的代码中,排名将在订阅完成之前 returned,因此它将使用尚未更新的排名数据。
我想你想要的可能是这样的:
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => {
// an array of all observables which will return the merged rank and member data
const ranksWithMembers = ranking.map(rank=>{
return this.memberService.get(rank.key).pipe(
map(member=>{
return {
...rank,
firstName: member.firstName,
lastName: member.lastName,
keyName: member.key,
}
})
)
})
// does not emit until all observables in array emit. Emits all results.
return forkJoin(ranksWithMembers)
}),
).subscribe(...)
我对你的代码没什么意见。
- 嵌套订阅不是很好的做法。你应该把它弄平。
- 使用
subscribe(next, error, complete)
complete 处理程序将标志预加载完成设置为完成 - 在你的情况下,我会使用插入到已排序的数组中,而不是在最后对整个数组进行排序。
看看下面的片段:
const orderedInsert = compareFn => (array, item) => {/** need to code this :( */};
const insetRank = orderedInsert((n1,n2) => {
// your compare fn
if(n1.points < n2.points) {
return 1;
}
if(n1.points > n2.points) {
return -1;
}
return 0;
}
);
this.rankingObs = this.rankingService.getAll().pipe(
mergeMap(ranking => from(ranking))
mergeMap(rank =>this.membersService.get(rank.key).pipe(map(member => ({
...rank,
...member
}))
).subscribe((rankMerged:RankingModelAll) =>
insetRank(this.rankingmodel, rankMerged),
e => console.log(e),
() => {
this.preloadingDone = true;
console.log('Done')
});