Using AngularFire2 I try to get data from a single Firestore document. What works is:
this.addressRef = afs.doc<Address>('addresses/key')
this.addressRef.valueChanges().subscribe(val => {......}
I want to run the subscription code just once. Normally I use take(1) to achieve this (works with the Firebase DB). But this code:
this.addressRef.valueChanges().take(1).subscribe(val => {......}
gives error: TypeError: this.addressRef.valueChanges(...).take is not a function.
VS Code is listing the take action. Is this a bug in AngularFire2, am I doing this wrong or is there an other (better) way to stop the subscription after the data is fetched? I also tried topromise but this also failed.
update
Because this answer has received a lot of attention, I have provided an updated answer. You should, in general, try to think reactively when programming with observables. There are some great tutorials, but this one is good.
New solution
user$ = this.afDs.doc<User>('users/NaGjauNy3vYOzp759xsc')
.valueChanges().pipe(
take(1) // Here you can limit to only emit once, using the take operator
)
And in your template, you subscribe to your observable.
{{(user$ | async).name}}
Context
This way of solving the problem has multiple benefits:
- If you wan't to transform data, you just throw in a map operator
- You can filter events with the rxjs filter operator
- Create other streams, based on the user$ stream
- easy debugging, because other developers can see the flow of data in your app in a more transparent way
For example (creating another stream, that only emits if the user is admin, and creates a new title):
adminTitle$ = this.user$.pipe(
filter(user => user.title === 'admin'),
map(user => `${user.name} (admin)`)
)
Old answer
You can achieve this by doing the following:
this.userDoc = afDs.doc<User>('users/NaGjauNy3vYOzp759xsc');
this.userDoc.valueChanges()
.pipe(take(1))
.subscribe(v => {
this.user = v;
});