我有一个对象数组,我需要将每个对象分别传递给异步方法(后面的进程用Promise处理,然后通过Observable.fromPromise(...)
转换回Observable - 需要这种方法,因为相同的方法是用于以下情况:只需单个对象随时传递;进程将对象保存到数据库中)。例如,这是一个对象数组:
[
{
"name": "John",
...
},
{
"name": "Anna",
...
},
{
"name": "Joe",,
...
},
{
"name": "Alexandra",
...
},
...
]
现在我有了一个名为insert which
的方法,它将对象插入到数据库中。数据库实例中的store
方法返回新创建的id。最后,复制初始对象并使用其新ID进行映射:
insert(user: User): Observable<User> {
return Observable.fromPromise(this.database.store(user)).map(
id => {
let storedUser = Object.assign({}, user);
storedUser.id = id;
return storedUser;
}
);
}
这适用于我插入单个对象的情况。但是,我想添加对插入多个对象的支持,这些对象只调用单个插入的方法。目前这就是我所拥有的,但它不起作用:
insertAll(users: User[]): Observable<User[]> {
return Observable.forkJoin(
users.map(user => this.insert(user))
);
}
insertAll
方法正在按预期插入用户(或者用该用户填充数据库的其他内容),但我没有得到任何回复。我正在调试正在发生的事情,似乎forkJoin
正在从第一个映射用户获得响应,但其他人被忽略。对insertAll
的订阅不会执行任何操作,也不会通过insertAll
上的catch或订阅insertAll
中的第二个参数发生任何错误。
所以我正在寻找一个解决方案,其中Observable(在insertAll
中)将以该形式向用户发回一系列新对象:
[
{
"id": 1,
"name": "John",
...
},
{
"id": 2,
"name": "Anna",
...
},
{
"id": 3,
"name": "Joe",,
...
},
{
"id": 4,
"name": "Alexandra",
...
},
...
]
我会很高兴任何指向正确方向的建议。提前谢谢!
答案 0 :(得分:7)
要从数组转换为可观察数据,您可以使用Rx.Observable.from(array)
。
要从observable转换为数组,请使用obs.toArray()
。请注意,这确实会返回一个数组的可观察对象,因此您仍然需要.subscribe(arr => ...)
才能将其删除。
也就是说,forkJoin
的代码看起来是正确的。但是如果你想尝试from
,请编写如下代码:
insertAll(users: User[]): Observable<User[]> {
return Observable.from(users)
.mergeMap(user => this.insert(user))
.toArray()
);
}
另一种更像rx的方法是在完成时发出值,而不是像forkJoin
或toArray
那样等待所有值。我们可以省略前一个示例中的toArray
,我们得到了它:
insertAll(users: User[]): Observable<User> {
return Observable.from(users)
.mergeMap(user => this.insert(user))
);
}
正如@cartant所提到的,问题可能不在Rx中,可能是您的数据库不支持多个连接。在这种情况下,您可以将mergeMap
替换为concatMap
,以使Rx仅发送1个并发请求:
insertAll(users: User[]): Observable<User[]> {
return Observable.from(users)
.concatMap(user => this.insert(user))
.toArray() // still optional
);
}