1

How can I refactor these nested arrays so that I can call something once all of the subscriptions have finished? I am sure it has to do with a combination of pipes, mergeMaps, concatMaps, etc.

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 => {

          });
        })
      })
2

2 Answers 2

2

With 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 
    }
)
Sign up to request clarification or add additional context in comments.

1 Comment

Simple Implementation, I like it
0

You can't listen on subscriptions, however, you could return an observable for each assignment an do a forkJoin of them, something like:

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

Now, I would refactor a little that code in order to make it more readable, something like:

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

p.s. Some alternative syntax I was thinking on is:

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

However, I'm not sure how it looks, although this may cause some underlying issues with V8, due to hidden classes.

Based on the other answer

I'm not much a fan of lodash, so I just wanted to present a vanilla js alternative:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.