идентифицировать последний объект в mergeMap - PullRequest
0 голосов
/ 06 января 2019

Я хочу объединить свою рейтинговую сущность с моей членской сущностью в 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 и выполнить сортировку по верхнему рангу?

Ответы [ 2 ]

0 голосов
/ 06 января 2019

У меня мало комментариев о вашем коде.

  1. Вложенная подписка - не очень хорошая практика. Вы должны сгладить это.
  2. Используйте обработчик subscribe(next, error, complete) complete для установки вашего флага preloadingDone на done
  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')
 });
0 голосов
/ 06 января 2019

возвращаемое значение в карте слияния должно быть наблюдаемым. В приведенном выше коде рейтинг будет возвращен до завершения подписки, поэтому он будет работать с данными рейтинга, которые еще не были обновлены.

Я думаю, что вы хотите что-то вроде:

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