Reputation: 151
I have 2 services. In one I want to subscribe to detect if a string changes in the other service to load from the database each time it changes.
First service:( The session value used is a reference to the 2nd service)
subscribeStringChange() {
this.session.uid.subscribe(x => {
console.log(this.session.uid);
return this.af.database.list('items', {
query: {
orderByChild: 'uid',
equalTo: this.session.uid
}
});
});
}
Here is the second service and what I have tried:
uid: Observable<string> = Observable.of('');
constructor(private auth: FirebaseAuth, private af: AngularFire) {
this.auth.subscribe(user => {
if (user) {
this.uid = Observable.of(user.uid);
console.info('logged in');
} else {
this.uid = Observable.of('');
console.info('logged out');
}
});
}
Upvotes: 3
Views: 2753
Reputation: 208944
You could use a BehaviorSubject
, which acts like both a producer and consumer (or more precisely, observer and observable). On the side where you use firebase, you would be acting on the producer side, emitting the new value, and on the other side, you just keep it the same
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
private _uid = new BehaviorSubject<string>('');
uid = this._uid.asObservable();
constructor(private auth: FirebaseAuth, private af: AngularFire) {
this.auth.subscribe(user => {
if (user) {
this._uid.next(user.uid);
console.info('logged in');
} else {
this.uid.next('');
console.info('logged out');
}
});
}
Notice the this._uid.next('')
. Here you are emitting a new value, and the subscriber(s) will receive it.
You don't need to change anything in the other service. Well actually you do. You are trying to access the uid
, which is an observable, when you should just use the value passed to the subscribe callback, x
this.session.uid.subscribe(x => {
console.log(x);
return this.af.database.list('items', {
query: {
orderByChild: 'uid',
equalTo: x
}
});
});
Upvotes: 2
Reputation: 41254
You've made things more complicated then they should be (: In general, you should use subscribe()
to assign end result of observable chain to a variable (for use in templates, for example). You shouldn't process observables in subscription...
Here's one solution you could use:
subscribeStringChange() {
// when user is authenticated
this.af.auth.filter(Boolean)
// get her 'uid'
.map(user => user.uid)
// and use it in another observable
.switchMap(uid => this.af.database.list('items', {
query: {
orderByChild: 'uid',
equalTo: uid
}
})
// finally, do something with the results
.subscribe(snap => console.log(snap));
}
Make sure you import operators somewhere in your code, in this case:
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
Upvotes: 1