Используйте rxjs / Typescript для отображения массива внутри ответа от внешнего API - PullRequest
0 голосов
/ 02 апреля 2020

Я новичок в Typescript / Javascript и пытаюсь разобраться с потенциалом rx js. Я использую этот код

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
  .pipe(
    map(o => ({
      numRecordings: o.numRecordings,
      numSpecies: o.numSpecies,
      page: o.page,
      numPages: o.numPages,
      recordings: o.recordings
    }))
  );

для сопоставления ответа API publi c с интерфейсом, IXenoCanto:

export interface IXenoCantoResponse {
    numRecordings: string;
    numSpecies: string;
    page: string;
    numPages: string;
    recordings: [];
  }

На самом деле recordings[], что я меня интересует. В последующем коде я использую поля в этом массиве для создания URL-адреса и добавления его к еще одному объекту:

data.forEach((element, index) => {
  let sub = element.sono['full'].substr(0, this.getPosition(element.sono['full'], '\/', 6));
  urls.push({
    id: index + 1,
    url: `${sub}${element['file-name']}`
  });

});

export interface IVoice {
  id: number;
  url: string;
}

Хотя этот код действительно работает, я был пытаясь сделать это более эффективно.

Интересно, можно ли отобразить отклик записей any[] прямо на IVoice[] в моем исходном коде карты. Поэтому я попытался изменить интерфейс IXenoCantoResponse следующим образом:

export interface IXenoCantoResponse {
    numRecordings: string;
    numSpecies: string;
    page: string;
    numPages: string;
    recordings: IVoice[]
    // recordings: [];
  }

И затем я могу попытаться сопоставить отклик [] с IVoice[] напрямую, примерно так:

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
      .pipe(
        map(o => ({
          numRecordings: o.numRecordings,
          numSpecies: o.numSpecies,
          page: o.page,
          numPages: o.numPages,
          recordings: o.recordings.map((element, index) => {

              id: index + 1,
              url: `${element.sono['full'].substr(0, this.getPosition(element.sono['full'], '\/', 6))}${element['file-name']}`
          }
          });
        }))
      );

Я до сих пор не смог получить второй подход к работе. Можно ли сделать это? Я думаю, что проблема заключается в том, как настроить оператор map с объектом массива. Правильно ли это, и может ли кто-нибудь указать мне правильное направление?

Редактировать:

Каждый объект в упомянутом выше массиве записей имеет следующий формат:

        {
            "id": "477551",
            "gen": "Troglodytes",
            "sp": "troglodytes",
            "ssp": "troglodytes",
            "en": "Eurasian Wren",
            "rec": "\u00c9tienne Leroy",
            "cnt": "Poland",
            "loc": "Hajn\u00f3wka, hajnowski, podlaskie",
            "lat": "52.6907",
            "lng": "23.6035",
            "alt": "160",
            "type": "song",
            "url": "\/\/www.xeno-canto.org\/477551",
            "file": "\/\/www.xeno-canto.org\/477551\/download",
            "file-name": "XC477551-190503-Troglodyte mignon@Sacharewo.mp3",
            "sono": {
                "small": "\/\/www.xeno-canto.org\/sounds\/uploaded\/ZWAQHOJFLZ\/ffts\/XC477551-small.png",
                "med": "\/\/www.xeno-canto.org\/sounds\/uploaded\/ZWAQHOJFLZ\/ffts\/XC477551-med.png",
                "large": "\/\/www.xeno-canto.org\/sounds\/uploaded\/ZWAQHOJFLZ\/ffts\/XC477551-large.png",
                "full": "\/\/www.xeno-canto.org\/sounds\/uploaded\/ZWAQHOJFLZ\/ffts\/XC477551-full.png"
            },
            "lic": "\/\/creativecommons.org\/licenses\/by-nc-sa\/4.0\/",
            "q": "A",
            "length": "1:13",
            "time": "08:00",
            "date": "2019-05-03",
            "uploaded": "2019-05-29",
            "also": [
                "Fringilla coelebs"
            ],
            "rmk": "Singing seated or in flight",
            "bird-seen": "yes",
            "playback-used": "no"
        }

1 Ответ

1 голос
/ 02 апреля 2020

Я думаю, вам нужно указать тип создаваемых объектов

return this.http.get<IXenoCantoResponse>(`${this.corsAnywhereUrl}${this.xenoCantoApiBaseUrl}${this.formatSearchTerm(searchTerm)}${this.recordingLength}`)
   .pipe(
      map(o => return new IXenoCantoResponse({
          numRecordings: o.numRecordings,
          numSpecies: o.numSpecies,
          page: o.page,
          numPages: o.numPages,
          recordings: o.recordings.map((element: IVoice, index) => new IVoice({
              id: index + 1,
              url: `${element['sono']['full'].substr(0, this.getPosition(element['sono']['full'], '\/', 6))}${element['file-name']}`
          })
        });
      }))
    );
...