识别 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(...)

我对你的代码没什么意见。

  1. 嵌套订阅不是很好的做法。你应该把它弄平。
  2. 使用 subscribe(next, error, complete) complete 处理程序将标志预加载完成设置为完成
  3. 在你的情况下,我会使用插入到已排序的数组中,而不是在最后对整个数组进行排序。

看看下面的片段:

    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')
 });