RxJS Observables数组以及要保留的其他数据

时间:2020-09-03 17:18:41

标签: angular typescript rxjs observable fork-join

简短说明

如何通过为我需要在forkJoinpipe中使用的每个Observable传递一些数据来处理可观察变量数组(例如,在map中)?

const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => [this.getDataFromApi(source[key]), key])

// resolve only observables[0][0], observables[0][1], observables[0][2] in magic way,
// but preserve  observables[1][0], observables[1][1], observables[1][2] for future use in pipe&map
const processedObservable = forkJoin(observables).pipe( // ???
  map(items => items.map(item => 'this is ' + item[0] + '(' + item[1] + ')')), // this doesn't work
  map(items => items.join(', '))
)

processedObservable.subscribe(text => console.log(text)) // subscribe only for test
// expected result: this is your cat (animal), this is your apple (fruit), this is your blue (color)

详细说明

我有一些“源”(项目的数组或对象)。我需要向API请求每个项,因此我得到了Observables数组。 接下来,我要处理所有接收到的数据,因此我使用forkJoin并在pipe和几个map中处理数据。

我无法直接处理订阅中的数据。

这是简单的示例:

const source = ['cat', 'apple', 'blue']
const observables = source.map(item => this.getDataFromApi(item))
const processedObservable = forkJoin(observables).pipe(
  map(items => items.map(item => 'this is ' + item)),
  map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: this is your cat, this is your apple, this is your blue

但是除了API请求的项目数据外,我还拥有在pipemap中处理期间必须使用的项目元数据。

这里是具有代表性来源的示例,但是这里我不使用项目的元数据(结果与上面相同)。我忽略了元数据:

const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => this.getDataFromApi(source[key]))
const processedObservable = forkJoin(observables).pipe(
  map(items => items.map(item => 'this is ' + item)),
  map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: this is your cat, this is your apple, this is your blue

这里是具有代表性来源的示例,但是在这里我忽略了键和API调用,但是我处理了项目的元数据:

const source = {animal: 'cat', fruit: 'apple', color: 'blue'}
const observables = Object.keys(source).map(key => of(key))
const processedObservable = forkJoin(observables).pipe(
  map(items => items.map(item => '(' + item + ')')),
  map(items => items.join(', '))
)
processedObservable.subscribe(text => console.log(text)) // test
// result: (animal), (fruit), (color)

我想得到这个结果

// result: this is your cat (animal), this is your apple (fruit), this is your blue (color)

通过某种方式在pipemap中:

  map(items => items.map(item => 'this is ' + item.apiValue + '(' + item.key + ')')),

或:

  map(items => items.map(item => 'this is ' + item[0] + '(' + item[1] + ')')),

但是我不知道如何将可观察变量和元数据数组传递给forkJoin,其中一些具有元数据的可观察变量数组:

const observables = Object.keys(source).map(key => [this.getDataFromApi(source[key]), key])

也许我应该使用其他功能,例如flatMapswitchMap

其他信息

用于模拟API调用的方法getDataFromApi

  getDataFromApi(item) {
    return of('your ' + item)
  }

4 个答案:

答案 0 :(得分:1)

以下是如何实现的示例:

from(Object.entries(source))
 .pipe(
   mergeMap(([key, value]) => getFromApi(value).pipe(
     map(item => `this is ${item} (${key})`), // <= key is being closured
   )),
   toArray(), // <= transform stream to array 
   map(item => item.join()), 

 )
 .subscribe(console.log);

尝试运行以下演示:

const { from, of } = rxjs;
const { map, switchMap, toArray } = rxjs.operators;

function getFromApi(item) {
  return of('your ' + item)
}

const source = { animal: "cat", fruit: "apple", color: "blue" };


from(Object.entries(source))
  .pipe(
    mergeMap(([key, value]) => getFromApi(value).pipe(
      map(item => `this is ${item} (${key})`), // <= key is being closured
    )),
    toArray(), // <= transform stream to array 
    map(item => item.join()),
  )
  .subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>

答案 1 :(得分:1)

您应将第一个map直接添加到创建各个可观察物的位置。

const source = { animal: "cat", fruit: "apple", color: "blue" };

const observables = Object.keys(source).map(key => getFromApi(source[key]).pipe(
  map(item => `this is ${item} (${key})`)
));

const processedObservable = forkJoin(observables).pipe(
  map(items => items.join(', '))
);

processedObservable.subscribe(console.log);

https://stackblitz.com/edit/rxjs-4x7hbv?file=index.ts

答案 2 :(得分:0)

function getDataFromApi(item) {
  return of('your ' + item)
}

const source = { animal: 'cat', fruit: 'apple', color: 'blue' };

from(Object.keys(source)).pipe(
  switchMap(key => forkJoin([getDataFromApi(source[key]), of(key)])),
  map(([data, key]) => `this is ${data} (${key})`),
  toArray(),
  map(data => data.join(', ')),
).subscribe(console.log);

请参阅:https://stackblitz.com/edit/rxjs-1t4nlo?file=index.ts

答案 3 :(得分:0)

尝试使用import { combineLatest } from 'rxjs'

 combineLatest(['cat', 'apple', 'blue'].map(item => this.getDataFromApi(item))).pipe(
    map(items => items.map(item => 'this is ' + item)),
    map(items => items.join(', '))
  )
  .subscribe({
    next:(res) => console.log(res)
  })

Example in stackblitz