【问题标题】:How can I refactor this RXJS / Angular code?如何重构这个 RXJS / Angular 代码?
【发布时间】:2018-06-01 23:33:50
【问题描述】:

如何重构这些嵌套数组,以便在所有订阅完成后调用某些内容?我确信它与管道、mergeMaps、concatMaps 等的组合有关。

this.teams = [
{
    Assignments: [{Id: 0, Name: 'assignment', Notes: 'notes'}]
},
{
    Assignments: [{Id: 0, Name: 'assignment', Notes: 'notes'}]
}]
    this.teams.map((team:any) => {
        team.Assignments.map((a: Assignment) => {
          return this.videoService.getById(a.VideoId).subscribe(
            res => {
              let e = new Event();
              e.Id = a.Id;
              e.title = a.Name;
              e.location = '';
              e.message = a.Notes;
              e.startDate = a.StartDate;
              e.endDate = a.EndDate;
              e.video = res;
              e.team = team.Name;
              this.eventList.push(e);
            },
            err => {

          });
        })
      })

【问题讨论】:

标签: javascript angular rxjs


【解决方案1】:

用lodash:

Observable.from(
    lodash.flatten(
        this.teams.map(team => team.Assignments)
        )
)
.flatMap(a => this.videoService.getById(a.VideoId))
. subscribe(
    res => {
        //handle individual responses
    },
    err => {},
    () => {
        //handle after all complete 
    }
)

【讨论】:

  • 简单的实现,我喜欢
【解决方案2】:

您不能收听订阅,但是,您可以为每个作业返回一个 observable,然后执行 forkJoin 其中一个,例如:

this.teams.map((team:any) => {
  forkJoin(...team.Assignments.map((a: Assignment) => {
    return this.videoService.getById(a.VideoId).map(
      res => {
        const e = new Event();
        e.Id = a.Id;
        e.title = a.Name;
        e.location = '';
        e.message = a.Notes;
        e.startDate = a.StartDate;
        e.endDate = a.EndDate;
        e.video = res;
        e.team = team.Name;
        this.eventList.push(e);
      });
  })).subscribe(data => {
    // Do something;
  })
})

现在,我将重构一些代码以使其更具可读性,例如:

function mapToEvent(team, assignment, response) {
  const e = new Event();
  e.Id = assignment.Id;
  e.title = assignment.Name;
  e.location = '';
  e.message = assignment.Notes;
  e.startDate = assignment.StartDate;
  e.endDate = assignment.EndDate;
  e.video = response;
  e.team = team.Name;
  return e;
}

this.teams.map(team => {
  forkJoin(
    ...team.Assignments.map(a =>
      this.videoService
        .getById(a.VideoId)
        .map(res => mapToEvent(team, a, res))
        .do(event => this.events.push(event))
    )
  ).subscribe(data => {
    // Do something;
  });
});

附言。我正在考虑的一些替代语法是:

function mapToEvent(team, assignment, response) {
  const obj = {
    Id: assignment.Id,
    title: assignment.Name,
    location: '',
    message: assignment.Notes,
    startDate: assignment.StartDate,
    endDate: assignment.EndDate,
    video: response,
    team: team.Name
  };

  return Object.assign(new Event(), obj);
}

但是,我不确定它的外观,尽管由于隐藏类,这可能会导致 V8 出现一些潜在问题。

基于其他答案

我不太喜欢 lodash,所以我只是想介绍一个 vanilla js 替代方案:

Observable.from(
  this.teams
    .map(team => team.Assignments)
    .reduce((acc, a) => [...acc, ...a], [])
)
  .flatMap(a => this.videoService.getById(a.VideoId))
  .catch(err => {
    // Do Something
  })
  .finally(() => {
    // Do something
  })
  .subscribe(res => {
    // Handle Single
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多