我有一个新的旅行'表单,用户可以在其中写入参与者的姓名,然后提交表单以创建旅行。
在提交时,我使用名称查询Firebase数据库,以获取参与者(/ users)的ID。然后我将ID添加到旅行对象的participantsID
字段,然后我将新旅程推送到Firebase。
问题是Firebase查询是异步并返回一个Observable,因此我的函数将在Observable完成之前继续推送对象,因此新对象的participantID字段为空。
是否有任何方法等待observable完成(以某种同步方式),以便我可以操作数据然后继续?到目前为止,我所有解决这个问题的尝试都失败了。
这是我的简单代码。
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);
}
答案 0 :(得分:1)
您可以通过执行Observable
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);
})
);
}
答案 1 :(得分:1)
最后,我使用@Pankaj Parkar的部分答案来解决问题。
我 public static void writeTGA(Bitmap src, String path) throws IOException {
ByteBuffer buffer = ByteBuffer.allocate(src.getRowBytes() * src.getHeight());
src.copyPixelsToBuffer(buffer);
boolean alpha = src.hasAlpha();
byte[] data;
byte[] pixels = buffer.array();
if (pixels.length != src.getWidth() * src.getHeight() * (alpha ? 4 : 3))
throw new IllegalStateException();
data = new byte[pixels.length];
for(int i=0;i < pixels.length; i += 4){// rgba -> bgra
data[i] = pixels[i+2];
data[i+1] = pixels[i+1];
data[i+2] = pixels[i];
data[i+3] = pixels[i+3];
}
byte[] header = new byte[18];
header[2] = 2; // uncompressed, true-color image
header[12] = (byte) ((src.getWidth() >> 0) & 0xFF);
header[13] = (byte) ((src.getWidth() >> 8) & 0xFF);
header[14] = (byte) ((src.getHeight() >> 0) & 0xFF);
header[15] = (byte) ((src.getHeight() >> 8) & 0xFF);
header[16] = (byte) (alpha ? 32 : 24); // bits per pixel
header[17] = (byte) ((alpha ? 8 : 0) | (1 << 4));
File file = new File(path);
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.write(header);
raf.write(data);
raf.setLength(raf.getFilePointer()); // trim
raf.close();
}
通过映射分割名称返回所有Observable,我订阅了Observable,结果包含一个数组数组,其中内部数组包含一个用户对象。
forkJoin
答案 2 :(得分:0)
你遇到了一个棘手的问题。在推送新旅行之前,您必须获取用户信息。
由于内存泄漏问题(或小心取消订阅),您不能每次都进行新的订阅。如果您使用的是Firebase,则可以使用AngularFire subject支持。
您可以使用查询中的主题(等于)更新订阅,然后推送用户使用.next(用户)进行检索。
然后你仍然需要等待所有用户。为此,您只能拥有一个订阅并同步获取所有ID或拥有多个订阅以更快地获得多个结果(但这很困难)。
为了解决这个问题,我创建了:
一个回调队列(只是数组,但使用push()和unshift()方法)
值列表
一个订阅的主题。
如果你想要一个ID,你必须:
你应该使用函数来推送,因为如果堆栈中没有值(要启动!),你必须调用.next()。 在您的订阅中,在其回调中,即当您收到远程用户对象时,您可以调用堆栈中的第一个回调。不要忘记弹出堆栈的值和回调,如果有的话,调用next()作为下一个值。
这样,您可以在最后一个用户的最后一个回调中推送您的行程。这就是所有的回调,这意味着你的应用程序不会中断。
我还没决定是否应该在云功能中这样做。因为用户必须保持连接,并且这使用他的数据/处理器。但是将所有代码放在同一个地方并且云功能仅限于Firebase的免费版本是件好事。 Firebase开发人员会提出什么建议?
我做了很多搜索以找到更好的解决方案,所以如果你有一个,请分享。我认为这有点复杂,但它的工作非常好。当用户想要添加新航班时我遇到了同样的问题,我需要先获取机场信息(coords)并推送多个对象(详细信息,地图等)