扁平化嵌套的可观察对象
Flattening nested Observables
我被嵌套的可观察对象困住了,需要一只手。
我有以下代码块
return this.findUser(term).map( users => {
return users.map( user => this.getLastLogin(user.user_id).map( last_login => {
user.last_login = last_login;
return user;
}));
});
findUser
返回Observable<User[]>
, getLastLogin
返回Observable<number>
。
我基本上希望获取一个用户列表,然后用另一个值的信息更新这个列表。
现在上面的代码返回<Observable<Observable<User>[]>
。
我想我可以用flatMap
代替最初的map
,但这会把对象变成<Observable<Observable<User>>
。
RxJS文档有点难以破译,所以我不确定switch
, forkJoin
或flatMap
的什么组合会让我得到我需要的。
我希望返回Observable<User[]>
。谁能给我指个正确的方向?
实际上,您不需要forkJoin()
或switch()
来完成此操作。
通常,您希望通过另一个异步调用来更新用户数组中的每个用户。
我想这样做:
var source = findUser('term')
.mergeAll()
.mergeMap(user => getLastLogin(user.user_id)
.map(last_login => {
user.last_login = last_login;
return user;
})
)
.toArray();
source.subscribe(val => console.log(val));
操作符mergeAll()
将高阶可观察对象转换为单个可观察对象。在本例中,它获取所有用户的数组,并逐一重新发出它们。然后mergeMap()
发出使用last_login
日期更新的用户。最后,我使用toArray()
将单个用户转换为一个大数组,该数组将它们作为整体发出(如果您想发出单个用户,则可以删除此操作符)。
注意,当你使用return users.map(...)
时,你使用的是返回一个数组的Array.map()
,而不是RxJS返回一个Observable的map()
。我认为处理单个对象通常比处理对象数组更容易。
查看实时演示:https://jsbin.com/naqudun/edit?js,console
打印到控制台:
[ { name: 'foo',
user_id: 42,
last_login: 2016-11-06T10:28:29.314Z },
{ name: 'bar',
user_id: 21,
last_login: 2016-11-06T10:28:29.316Z } ]
一种解决方案是使用forkJoin
加入,然后将调用getLastLogin
的结果映射到用户:
// forkJoin will return Observable<User[]>, so use switchMap.
return this.findUser(term).switchMap(users => Observable.forkJoin(
// Map the array of users to the array of observables to be joined. Use
// first to ensure the observables complete.
users.map(user => this.getLastLogin(user.user_id).first()),
// Use forkJoin's selector to add the last_login to each user and return
// the users.
(...logins) => {
users.forEach((user, index) => { user.last_login = logins[index]; });
return users;
}
));
正如@martin指出的,mergeAll()是解决方案。您也可以在map操作结束时应用它。
使用最新的语法,它读作:
getStations(factoryId: number): Observable<Station[]> {//...omitted}
getAllStations(): Observable<Station[]> {
const result = this.factoriesService.getFactories().pipe(
map(factories => factories.map(f => f.id)),
mergeMap(factoryIds => factoryIds.map(id => this.getStations(id))),
mergeAll()
);
return result;
}
- 在ko.applyBindings(..)中执行Knockout js订阅函数(用于可观察对象)
- Knockout.js用单个json对象绑定一个可观察对象
- 根据某些条件将 JS 绑定到可观察对象内的数组元素
- 如何从挖空可观察对象中获取所选项目的文本
- 从另一个可观察对象获取价值的最佳方法,而无需组合最新
- 可观察对象的角 2 条件链接
- 观察对象是否已更改
- 如何在 angularjs 中观察对象中的对象
- 将通过原型计算的可观察对象添加到构造函数中
- 挖空解包可观察对象无法按预期工作
- 如何从可观察对象数组中删除项目
- 使用 Knockout 和 Typescript.如何从订阅中更改可观察对象的值
- Knockout+Moment.js–更新可观察对象内的相对日期
- 在AngularJS中观察对象
- 角度,观察对象中的特定关键点
- 微风导航阵列成员是淘汰赛中的可依赖观察对象
- 在knockout.js中为可观察对象添加属性后为什么出现TypeError
- Knockout js,访问循环外的可观察对象
- 敲除:绑定到同一可观察对象的几个 DOM 元素
- KnockoutJS-一个计算可写的可观察对象;无法正确更新绑定