Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 等待Observable完成以提交表单_Javascript_Angular_Firebase_Observable_Angularfire2 - Fatal编程技术网

Javascript 等待Observable完成以提交表单

Javascript 等待Observable完成以提交表单,javascript,angular,firebase,observable,angularfire2,Javascript,Angular,Firebase,Observable,Angularfire2,我有一个“新旅行”表单,用户可以在其中填写参与者的姓名,然后提交表单来创建旅行。 提交时,我使用名称查询Firebase数据库,以获取参与者的ID(/users)。然后,我将ID添加到trip对象的participantsID字段,然后将新的trip推送到Firebase 问题是Firebase查询是异步的,并且返回一个可观察对象,因此我的函数将在可观察对象完成之前继续推送对象,因此新对象的participantsID字段为空 有没有什么方法可以等待可观察对象完成(以一种同步的方式),以便我可以

我有一个“新旅行”表单,用户可以在其中填写参与者的姓名,然后提交表单来创建旅行。 提交时,我使用名称查询Firebase数据库,以获取参与者的ID(/users)。然后,我将ID添加到trip对象的
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()方法)

  • 一列值

  • 一次订阅一个主题

如果您想要ID,您必须:

  • 推动价值
  • 按下将检索返回值的回调
您应该使用函数来推送,因为如果堆栈中没有值,就必须调用.next()。 在订阅中,在其回调中,即当接收到远程用户对象时,可以调用堆栈中的第一个回调。不要忘记弹出您的值和堆栈回调,如果有下一个值,则调用next()。

这样,您就可以在最后一个用户的最后一次回调中推送您的行程。这些都是回调,这意味着你的应用程序不会被中断

我还没有决定我们是否应该在云函数中这样做。因为用户必须保持连接,这需要使用他的数据/处理器。但是,将所有代码放在同一个位置是很好的,而且对于免费版本的Firebase来说,云功能是有限的。Firebase开发人员有什么建议


为了找到更好的解决方案,我做了很多搜索,如果你有,请分享。我认为这有点复杂,但它工作得很好。当用户想要添加新航班时,我也遇到了同样的问题,我需要在之前获取机场信息(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
返回承诺。。