对于在TypeScript中使用Angular2编写的Web应用程序,我需要使用RxJs Observable
。
由于我以前从未使用过rxjs,而且我对一般的反应编程不熟悉,因此我有时难以找到正确的方法来做某些特定的事情。
我现在面临一个问题。我必须将Array<Observable<T>>
转换为Observable<Array<T>>
我将尝试用一个例子来解释它:
- 我有一个Observable
,它为我提供了Users
(Observable<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}}?
答案 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))
答案 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']
});