I have working code that queries Firestore and returns an Observable of type ImageUploadWId[]
. I would like to return a Promise
instead. This is because
- my data isn't changing often;
- I am performing deletes based on the data that comes in.
SnapshotChanges()
returns an array of actions. The first action contains an incomplete array of size 1. The last action contains an array of size 4. The last array is complete; it has all the ImageUploadWIds
from the one groupId
.
I want just one array that has the ImageUploadWIds
from only the designated groupId. Using a Promise is giving me the ImageUploadWIds
from all the groupIds
. I believe the where clause isn't working.
Here is my working code, which only prints imageUpload
groupIds from one groupId, but returns more than one array. The last array is the only one I need. Edit (added log statements):
getImageInfosWIds(bathroomGroupId: string): Observable<ImageUploadWId[]> {
return this.afs.collection(this.bathroomImagesLocation,
ref => ref.where('groupId', '==', bathroomGroupId)).snapshotChanges()
.map(actions => {
return actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
const imageUpload = new ImageUploadWId();
imageUpload.set(id, <ImageUpload>data);
return imageUpload;
})
})
}
onDeleteGroup(groupId: string) {
this.bathroomGroupService.getImageInfosWIds(groupId)
.subscribe((imageUploads) => {
console.log("imageUploads.length: " + imageUploads.length);
for (let imageUpload of imageUploads) {
console.log("(groupId, filename): (" + imageUpload.groupId + ", " + imageUpload.filename + ")");
}
})
}
Here is my code trying to use a Promise. This prints imageUploads from both of my groups instead of only from the given bathroomGroupId.
getImageInfosWIds(bathroomGroupId: string): Promise<QuerySnapshot> {
return this.afs.collection(this.bathroomImagesLocation,
ref => ref.where("groupId", "==", bathroomGroupId))
.ref
.get();
}
onDeleteGroup(groupId: string) {
this.bathroomGroupService.getImageInfosWIds(groupId)
.then( (querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log("edit-bathrooms: " + doc.data().groupId);
})
},
() => {console.log("Error in edit-bathrooms. promise unfullfilled " +
"in onDeleteGroup( " + groupId + " )")});
}
Edit: This is the final code that worked:
onDeleteGroup(groupId: string) {
this.bathroomGroupService.getImageInfosWIdsObservable(groupId)
.pipe(take(1)).subscribe(
data => {
console.log(data[0].groupId);
});
}
getImageInfosWIdsObservable(bathroomGroupId: string) {
return this.afs.collection(this.bathroomImagesLocation,
ref => ref.where('groupId', '==', bathroomGroupId)).snapshotChanges() //rxjs 5 -> 6 library
.pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data();
const documentId = a.payload.doc.id;
const imageUpload = new ImageUploadWId();
imageUpload.set(documentId, <ImageUpload>data);
return imageUpload;
}))
);
}
Just one final word. If you're still getting an extra array, you may have subscribed to the same Firestore collection in another part of your code and not unsubscribed. That was part of my problem.
AngularFire2 wraps the Firebase reference, so calling
.ref.get()
creates a new reference and ignores the query function you supplied.Luckily, RxJS makes it easy to convert an Observable to a Promise. You just need to pipe in
first()
ortake(1)
to force the Observable to complete (otherwise the promise will never resolve because Firebase provides an endless realtime stream).It should be,