Emeric
Emeric

Reputation: 6885

Firebase good use of Observable (rxjs) on angular 2+

At this moment I'm using Subject from Rxjs without any problem, simple example:

Service

 rooms: Room[] = [];
    roomsSubject = new Subject<Room[]>();

    emitRooms() {
        this.roomsSubject.next(this.rooms);
    }

    getRooms() {
        firebase.database().ref('/rooms').on('value', data => {
            this.rooms = data.val() ? Object.values(data.val()) : [];
            console.log(data.val());
            this.emitRooms();
        }, error => {
            console.log("getRooms: ", error);
        });
    }

Component:

rooms: Room[];
roomsSubscription: Subscription;
ngOnInit() {
    this.roomService.getRooms();
    this.roomsSubscription = this.roomService.roomsSubject.subscribe((rooms: Room[]) => {
        this.rooms = rooms;
    });

}

All is working fine but in this case I just need an Observable (I don't emit datas from client). So I tried to update this code to:

getRooms() {
    return firebase.database().ref('/rooms').on('value', data => {
        return of(data.val());
        
    }, error => {
        console.log("getRooms: ", error);
    });
}

Component:

ngOnInit() {
    this.roomsSubscription = this.roomService.getRooms().subscribe((rooms: Room[]) => {
        this.rooms = rooms;
    });

}

Error when subscribe:

error TS2339: Property 'subscribe' does not exist on type '(a: DataSnapshot, b?: string) => any'

After updating to:

getRooms(): Observable<any> {

I got:

error TS2322: Type '(a: DataSnapshot, b?: string) => any' is not
assignable to type 'Observable<any>'.   Property '_isScalar' is
missing in type '(a: DataSnapshot, b?: string) => any'.

All the time I followed stackoverflows to correct my errors and all the time I got new errors. I'm developing on Visual Studio Code.

Is there a chance to use Observable without Angularfire?

Upvotes: 0

Views: 532

Answers (1)

SiddAjmera
SiddAjmera

Reputation: 39432

The reason for error is that you're returning whatever is returned from firebase.database().ref('/rooms').on(...) which is a value of type (a: DataSnapshot, b?: string) => any. What you want to send is Observable instead.

For that, you could simply use Observable.create in this case. And in case of an error, you could use throwError:

...
import { Observable, throwError } from 'rxjs';
...

@Injectable()
export class RoomService {

  getRooms(): Observable<any> {
    return Observable.create(observer => {
      firebase.database().ref('/rooms').on('value', data => {
        return observer.next(data.val());
      }, error => {
        return throwError(error);
      });
    });
  }

}

Upvotes: 2

Related Questions