Как мне подписаться на Observable и использовать это значение в объекте Javascript? - PullRequest
0 голосов
/ 05 июля 2019

Я довольно новичок в Observables, RxJS и Angular в целом. Я использую Angular 7 (Ionic 4) и с трудом нахожу решение проблемы ниже.

В моем приложении я делаю HTTP-запрос GET следующим образом:

myData = this.http.get("https://example.com/api").pipe(
  map(results => {
    return results["payload"]
  })
)

Этот HTTP-запрос GET возвращает Observable myData, который имеет следующие данные:

const data = [
  {
    "id": 1,
    "name": "abc",
    "description": "test1" 
  },
  {
    "id": 2,
    "name": "def",
    "description": "test2" 
  },

  ...

  ...

]

Я хочу добавить еще один ключ color к каждому объекту в этом массиве следующим образом:

const data = [
  {
    "id": 1,
    "name": "abc",
    "description": "test1",
    "color": "green"
  },
  {
    "id": 2,
    "name": "def",
    "description": "test2",
    "color": "red"
  },

  ...

  ...

]

Вместо жесткого кодирования значения color для каждого объекта, я хочу извлечь это значение ключа из функции getColor(id), которая находится в другой службе с именем colorService.

Проблема в том, что colorService.getColor(id) возвращает наблюдаемое.

Вопрос: Как подписаться на colorService.getColor(id) для каждого объекта в моем массиве?

Я хочу сделать что-то вроде этого:

const data = [
  {
    "id": 1,
    "name": "abc",
    "description": "test1",
    "color": <subscribe to colorService.getColor(1)>
  },
  {
    "id": 2,
    "name": "def",
    "description": "test2",
    "color": <subscribe to colorService.getColor(2)>
  },

  ...

  ...

}

Надеюсь, я в порядке. Мои концепции довольно слабы на данный момент, поэтому извиняюсь, если некоторые из них звучат запутанно.

1 Ответ

2 голосов
/ 05 июля 2019

Это то, что вы можете сделать [См. Объяснение в комментариях к коду] -

myData = this.http.get("https://example.com/api")
                      .pipe(
                              mergeMap(results => {
                                const data = results["payload"];
                                //I am assuming that `data` is the array that you mentioned in your question
                                //Iterate through each of the object in the array and map it to an observable which
                                //will fetch the color and then return the data with color

                                //obs will be an array of observables for each data
                                const obs = data.map(d => {                                  
                                  return this.colorService.getColor(d.id)
                                             .pipe(
                                               map(color => {
                                                 return {...d, color};
                                               })
                                             );
                                });

                                //wait for all the obs to be returned;
                                return forkJoin(obs);
                              }),
                              tap(dataArrayWithColor => {
                                //dataArrayWithColor will have an array of object which will have data with color
                                console.log(dataArrayWithColor);
                              })
                          );

Надеюсь, это поможет.

...