识别mergeMap中的最后一个对象

时间:2019-01-06 13:02:58

标签: angular ionic-framework rxjs angularfire

我想将我的排名实体与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 :(得分:1)

合并映射中的返回值应该是可观察的。在上面的代码中,排名将在订阅完成之前返回,因此它将与尚未更新的排名数据一起使用。

我认为您想要的可能是这样的:

    public boolean onOptionsItemSelected(MenuItem item) {

        final View view = getView();

        final AppBarLayout yearBar = view.findViewById(R.id.yearbar);
        final CoordinatorLayout cLayout = view.findViewById(R.id.main_content);

        switch (item.getItemId()) {
            case R.id.year_dropdown:
                if (yearBar.getTag().toString().trim().equals("on")) {
                    yearBar.setVisibility(View.GONE);
                    yearBar.setTag("off");

                } else if (yearBar.getTag().toString().trim().equals("off")) {
                    yearBar.setVisibility(View.VISIBLE);
                    yearBar.setTag("on");

                    cLayout.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            yearBar.setVisibility(View.GONE);
                            yearBar.setTag("off");
                            Toast.makeText(getActivity(),"Click detected!", Toast.LENGTH_LONG).show();
                        }
                    });

                }
                return true;

            case R.id.settings:
                // Open settings
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

答案 1 :(得分:1)

我对您的代码没什么评论。

  1. 嵌套订阅不是很好的做法。您应该将其弄平。
  2. 使用subscribe(next, error, complete) complete 处理程序将您的标志preloadingDone设置为完成
  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')
 });