rxjs Оператор, который преобразует Observable <List <X>> в Observable <X> - PullRequest
0 голосов
/ 27 апреля 2018

Я работаю с не очень удобным API, использующим Angular HTTP и rxjs. Я пытаюсь вернуть Observable<List<Object>> из моего сервиса. Вот пример JSON, который возвращается из моего запроса get:

Items: {
​​    "$type": "System.Collections.Generic.List`1[[Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts]], mscorlib"
​​    "$values": [
       Object { "$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts", EntityTypeName: "7", Properties: {…} }
       Object { "$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts", EntityTypeName: "7", Properties: {…} }
       Object { "$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts", EntityTypeName: "7", Properties: {…} }
    ]
}

А затем внутри каждого объекта:

{
  "$type": "Asi.Soa.Core.DataContracts.GenericEntityData, Asi.Contracts"
   EntityTypeName: "7"
   Properties: {
    "$type": "Asi.Soa.Core.DataContracts.GenericPropertyDataCollection, Asi.Contracts"
    "$values": {}
}

Мне нужно извлечь $values для каждого элемента, а затем вернуть список $values объектов. Но я не могу понять, как это сделать с Angular и rxjs без подписки. И я не хочу подписываться, так как хочу, чтобы компонент , а не service , обрабатывал полученные данные.

Я искал в rxjs Operators решение моей проблемы. Но, похоже, нет оператора, который преобразует List<X> в X при сохранении наблюдаемой.

Возможно ли это сделать с Angular2 + и rxjs? Или, может быть, есть лучший способ выполнить эту задачу. Я относительно новичок в реактивном программировании, поэтому любые общие советы будут оценены.

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Используйте Observable#mergeMap (часто называемый flatMap в других реализациях).

mergeMap позволяет:

  1. map каждый из ваших элементов в списки (то есть, выдает список значений для каждого события)
  2. объединить списки обратно в один поток событий

При условии получения следующих данных:

const result = {
  items: {
    $type: 'something something',
    $values: [1, 2, 3]
  }
}

Вы можете получить Observable его значений, используя следующее:

Rx.Observable.of(result).mergeMap(x => x.items.$values)

Например:

Rx.Observable
  .of(result)
  .mergeMap(x => x.items.$values)
  .subscribe(value => console.log(`new value: ${value}`));

... распечатал бы:

новое значение: 1
новое значение: 2
новое значение: 3

0 голосов
/ 27 апреля 2018

Вы преобразовываете элементы в RxJS с помощью оператора map (). Он применяет изменение к каждому элементу в потоке и возвращает измененный.

Цель подписки () - сделать все функции RXJS, инициируемые в первую очередь. Потому что даже когда холодная наблюдаемая приобретает новое значение, с ней ничего не происходит, если только в конце концов не будет подписки. Так что вы можете сделать

const sub = $stream.map(originalValue => {return transformToX(originalValue);})
.subscribe(transformedValue => {
    emitter.emit(transformedValue);
});

Или для более четкой демонстрации цели подписки:

const sub = $stream.map(originalValue => {return transformToX(originalValue);})
.do(transformedValue => {
    emitter.emit(transformedValue);
})
.subscribe();

Не забудьте отписаться от всех подписок, когда они вам больше не нужны! См. http://brianflove.com/2016/12/11/anguar-2-unsubscribe-observables/.

...