2016-05-02 147 views
13

对于在TypeScript中使用Angular2编写的Web应用程序,我需要使用RxJs Observable s。
因为我从来没有使用过rxjs,而且我也是一般的新手,所以我有时会遇到一些困难,找到正确的方法去做一些特定的事情。
我现在面临一个问题。我必须将Array<Observable<T>>转换为Observable<Array<T>>
我会尝试用一个例子来解释一下:
- 我有一个Observable,这给了我的UsersObservable<Array<User>>
名单 - 该User -class具有功能getPosts返回一个Observable<Array<Post>>
- 我需要将Observable<Array<User>>映射到Observable<Array<Post>>以评估onNext函数中的所有PostRxJs阵列可观察阵列

我可以从Observable<Array<User>>使用
map((result : Array<User>) => result.map((user : User) => user.getPosts()))
ANS容易映射到Observable<Array<Observable<Array<Post>>>>我可以变平的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'. 

所以我的问题是:
我如何 “扁平化” 的ObservablesArrayArray

+0

getPosts方法对应什么?它是否加载特定用户的帖子? –

回答

22

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()返回一个可观察......

有了这个,你将收到帖子的数组的数组:

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

是的'getPosts()'返回'Observable >'。所以我想这就是我正在寻找的。我会尽快尝试,并让你知道它是否工作。谢谢 – Springrbua

+0

完美地工作。我只是用'forkJoin'替换'combineLatest'。非常感谢! – Springrbua

3

您可以使用功能上rxjs方法适用你想,像这样:

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 
 

 
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>

+0

我想这应该工作,但我现在坚持'forkJoin'。 – Springrbua