Javascript 等待Observable完成以提交表单
我有一个“新旅行”表单,用户可以在其中填写参与者的姓名,然后提交表单来创建旅行。 提交时,我使用名称查询Firebase数据库,以获取参与者的ID(/users)。然后,我将ID添加到trip对象的Javascript 等待Observable完成以提交表单,javascript,angular,firebase,observable,angularfire2,Javascript,Angular,Firebase,Observable,Angularfire2,我有一个“新旅行”表单,用户可以在其中填写参与者的姓名,然后提交表单来创建旅行。 提交时,我使用名称查询Firebase数据库,以获取参与者的ID(/users)。然后,我将ID添加到trip对象的participantsID字段,然后将新的trip推送到Firebase 问题是Firebase查询是异步的,并且返回一个可观察对象,因此我的函数将在可观察对象完成之前继续推送对象,因此新对象的participantsID字段为空 有没有什么方法可以等待可观察对象完成(以一种同步的方式),以便我可以
participantsID
字段,然后将新的trip推送到Firebase
问题是Firebase查询是异步的,并且返回一个可观察对象,因此我的函数将在可观察对象完成之前继续推送对象,因此新对象的participantsID字段为空
有没有什么方法可以等待可观察对象完成(以一种同步的方式),以便我可以操作数据,然后继续?到目前为止,我所有修复此问题的尝试都失败了
这是我的简单代码
getUserByAttribute(attribute, value) {
return this.db.list('/users', {
query: {
orderByChild: attribute,
equalTo: value,
limitToFirst: 1
}
});
}
createTrip(trip) {
for(let name in participantsName.split(',')) {
getUserByAttribute('username', name)
.subscribe( user => trip.participantsID.push(user[0].$key) );
}
this.db.list('/trips').push(trip);
}
通过执行
forkJoin
createTrip(trip) {
var observableArray: any = participantsName.split(',')
.switchMap((name)=> getUserByAttribute('username', name))
Observable.forkJoin(observableArray).subscribe(
trips => trips.forEach((trip) => {
this.db.list('/trips').push(trip);
})
);
}
你有个难题。在推送新行程之前,您必须获取用户信息 由于内存泄漏问题,您不能每次都进行新订阅(或小心取消订阅)。如果您使用的是Firebase,则可以使用支持 您可以通过在查询中使用主题(等于)来更新订阅,然后使用.next(user)推送用户进行检索 然后您仍然需要等待所有用户。为此,您可以只有一个订阅并同步获取所有ID,也可以有多个订阅以更快地获取多个结果(但这很困难) 为了解决这个问题,我创建了:
- 回调队列(仅使用数组,但使用push()和unshift()方法)
- 一列值
- 一次订阅一个主题
- 推动价值
- 按下将检索返回值的回调
为了找到更好的解决方案,我做了很多搜索,如果你有,请分享。我认为这有点复杂,但它工作得很好。当用户想要添加新航班时,我也遇到了同样的问题,我需要在之前获取机场信息(coords)并推送多个对象(细节、地图等)。最后,我使用@Pankaj Parkar的部分答案来解决问题。 我
forkJoin
通过映射拆分名称返回的所有可观察对象,我订阅该可观察对象,其结果包含一个数组数组,其中内部数组包含一个用户对象
getUserByAttribute(attribute, value) {
return this.db.list('/users', {
query: {
orderByChild: attribute,
equalTo: value,
limitToFirst: 1
}
}).first();
}
createTrip(trip) {
Observable.forkJoin(
trip.participantsName.split(',')
.map(name => getUserByAttribute('name', name))
).subscribe(
participants => {
trip.participants = participants.map( p => p[0].$key);
this.tripService.createTrip(trip);
}
);
}
}
问题是我需要将所有用户ID添加到我的单个
trip
对象中,然后再将其推送到数据库中。我可以在subscribe函数中添加它们,但是在我将每个Id添加到对象后,如何将trip
对象推送到数据库中呢?我还得到了错误participantsName.split(…)。switchMap不是一个函数
,这是很多事情,你能给我举个例子吗?我觉得我想完成一件简单的事情,比如在发送表单之前获取一些数据,但要知道我的答案有帮助,这比我想象的要复杂得多。。我使用了switchMap
,因为我认为getAttribute
返回承诺。。