0
votes

I created an API that stores a list of fixtures and characteristics about them. I can pull a list (potentially filtered) of all of the fixtures.

I also created a separate API that provides an interface to an existing data source. This data source records instances of use of the fixtures, and the API provides a sum of the time that the fixture was in use since a given date. Since each fixture will have a different date, I have to make individual API calls. Unfortunately, because of some corporate security zone policies I can't just do the combining on the back end, I have to do it in the front end.

My goal is to create an Angular service that returns an observable of a list of fixtures combined with their duration of use.

I've tried using mergeMap, and looping over the resulting list of fixtures, calling service for the correct fixture, but this never made the call, I think it only created the observable, but didn't subscribe. Subscribing threw a different error. I wish I saved all of the attempts, but I'll show what I have below.

I'm calling this function with this code in my component, and displaying it in a table:

getFixturesTable() {
    this.fixtureListService.getFixturesTable()
      .subscribe(fixtures => {
        this.fixtureSource = new MatTableDataSource<FixtureListModel>(fixtures);
        this.fixtureSource.paginator = this.paginator;
        this.fixtureSource.sort = this.sort;
      });
  }

This one doesn't get a list to the final map where I apply the adapter, it only passes one object, not an array, even though I'm returning fixtures and not fixture. Error is "data.map is not a function".

public getFixturesTable(
      fixtureSerial = '',
    ): Observable<FixtureListModel[]> {
      return this.fixtures.getFixtures(fixtureSerial).pipe(
        mergeMap((fixtures: any[]) => {
          fixtures.map((fixture: any) => {
            this.times.getSerialDuration(fixture.serial, fixture.latest_inspection).pipe(
              map(use => fixture.duration = use.duration)
            );
          });
          return fixtures;
        }),
        map((data: any[]) => {
          console.log(data);
          return data.map(item => this.fixtureListAdapter.adapt(item));
          }
        )
      );
    }

This one actually executes the api calls, but they come in late and never get applied to the fixture object, at least as far as I can tell. I think it has something to do with using the .subscribe function in the map, but I've read that that could be bad practice.

public getFixturesTable(
      fixtureSerial = '',
    ): Observable<FixtureListModel[]> {
      return this.fixtures.getFixtures(fixtureSerial).pipe(
        mergeMap((fixtures: any[]) => {
          console.log('looping');
          fixtures.map((fixture: any) => {
            console.log(fixture);
            this.times.getSerialDuration(
              fixture.serial,
              fixture.latest_inspection,
            ).subscribe( agg =>
              fixture.duration = agg.duration
            );
            console.log(fixture);
            return fixture;
          });
          return fixtures;
        }),
        map((data: any[]) => data.map(item => this.fixtureListAdapter.adapt(item))
        ));
    }

I wish I had saved some of the other attempts that were close, but unfortunately they are lost t time.

What I'm really trying to do I guess is perform an "inner join" using Observables and the HttpClient. I'd like to find a general method for doing this if it comes up again, but in this case I just need to add the "fixtures.duration" field to the fixtures object, then display it in the table.

1

1 Answers

0
votes

So I got this to work, I think I may have been looking at the wrong result. Either way I'm not a fan of the subscribe calls inside of the map, unless that's the best way to do it.

public getFixturesTable(
      fixtureSerial = '',
    ): Observable<FixtureListModel[]> {
      return this.fixtures.getFixtures(fixtureSerial).pipe(
        map((data: any[]) => data.map(item => this.fixtureListAdapter.adapt(item))),
        map(fxs => {
          fxs.map(fixture => {
            this.times.getSerialDuration(
              fixture.serial.toString(),
              fixture.latestInspection)
              .subscribe(time => fixture.usedTime = time.duration);
          });
          return fxs;
        }),
        );
    }