RxJs可观察数组的数组

时间:2016-05-02 13:49:09

标签: typescript angular rxjs observable

对于在TypeScript中使用Angular2编写的Web应用程序,我需要使用RxJs Observable。 由于我以前从未使用过rxjs,而且我对一般的反应编程不熟悉,因此我有时难以找到正确的方法来做某些特定的事情。
我现在面临一个问题。我必须将Array<Observable<T>>转换为Observable<Array<T>> 我将尝试用一个例子来解释它:
- 我有一个Observable,它为我提供了UsersObservable<Array<User>>)的清单 - User - 类的函数getPosts返回Observable<Array<Post>> - 我需要将Observable<Array<User>>映射到Observable<Array<Post>>以评估Post函数中的所有onNext s。

我可以使用
轻松地从Observable<Array<User>>映射到Observable<Array<Observable<Array<Post>>>> map((result : Array<User>) => result.map((user : User) => user.getPosts()))
我可以将Array<Array<Post>>压平为Array<Post> 但是,我找不到将Observable<Array<Observable<Array<Post>>>>映射到Observable<Array<Array<Post>>>的正确方法 到目前为止,我将combineLatest函数与flatMap一起使用 对我来说它似乎工作,我使用的编辑器(Atom编辑器)没有显示任何错误。但是现在我使用Netbeans,它在这段代码中显示错误。使用“tsc”编译代码也会导致错误 看起来像这样:

Argument of type '(result: Post[]) => void' is not assignable to parameter of type 'NextObserver<[Observable<Post>]> | ErrorObserver<[Observable<Post>]> | CompletionObserver<[...'.
Type '(result: Post[]) => void' is not assignable to type '(value: [Observable<Post>]) => void'.  

所以我的问题是:
如何将Array Observables Array“展平”为{{1}}?

5 个答案:

答案 0 :(得分:30)

flatMap运算符允许这样做。我不完全明白你尝试做什么,但我会尝试提供答案......

如果你想加载所有

getPostsPerUser() {
  return this.http.get('/users')
    .map(res => res.json())
    .flatMap((result : Array<User>) => {
      return Observable.forkJoin(
        result.map((user : User) => user.getPosts());
    });
}

Observable.forkJoin允许您等待所有可观察者都收到数据。

上面的代码假定user.getPosts()返回一个observable ......

有了这个,您将收到一系列帖子:

this.getPostsPerUser().subscribe(result => {
  var postsUser1 = result[0];
  var postsUser2 = result[1];
  (...)
});

答案 1 :(得分:8)

您可以在所需的rxjs方法上使用apply函数,如下所示:

const source1 = Rx.Observable.interval(100)
  .map(function (i) { return 'First: ' + i; });

const source2 = Rx.Observable.interval(150)
  .map(function (i) { return 'Second: ' + i; });

const observablesArray = [source1, source2];

const sources = Rx.Observable.combineLatest
.apply(this, observablesArray).take(4)

/* or you can write it without "apply" this way:
const sources = Rx.Observable
                .combineLatest(...observablesArray)
                .take(4)
*/
sources.subscribe(
  (response) => {
    console.log(response);
  }
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.1/Rx.min.js"></script>

答案 2 :(得分:2)

在这个可观察数组上使用forkJoin,然后它将是一个可观察的数组。

答案 3 :(得分:1)

这是一些使用rxjs@6.3.3的示例代码

import { of, forkJoin} from 'rxjs';
import { Observable } from 'rxjs'

const source:Array<Observable<String>> = [of('A'), of('B'), of('C') ];

forkJoin(source).subscribe( (x)=> console.log(x))

https://arrayofobservablesexamp.stackblitz.io

答案 4 :(得分:0)

使用toArray()

range(0, 7).pipe(
  concatMap(v => of(`day_${v}`)),
  toArray() // here
).subscribe(a => {
  console.log(a); // ['day_0', 'day_1', ... 'day_6']
});