Thomas Degroot
Thomas Degroot

Reputation: 524

how do I convert a promise to observable in a Ionic 4 firebase PWA app

The following code worked previously with an Ionic/Cordova App that I built. I am attempting to build an Ionic PWA app reusing some previous code But now the

public List: Observable<any>; 

does not seem to change the

this.List = this.messageService.getMessageList().valueChanges(); 

to an Observable and now returns the Uncaught (in promise): error. I have previously used the this.List to return the firebase data and display it. I have gone through my package.json data and I am still using the same rxjs, firebase and anglefire. The only missing pieces are the Firebase Cordova plugins. Any ideas what I am missing?

message.ts

import { Component, OnInit} from '@angular/core';
import { MessageService } from '../../services/messages/message.service';
import { Observable } from "rxjs";

@Component({
  selector: 'app-message',
  templateUrl: './message.page.html',
  styleUrls: ['./message.page.scss'],
})

export class MessagePage implements OnInit {
  public List: Observable<any>;

  constructor(
    private messageService: MessageService,
  ) {}

  ngOnInit() {
  this.List = this.messageService.getMessageList().valueChanges();
  console.log('List', this.List);
  }
}

service.ts

import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';

@Injectable({
  providedIn: 'root'
})

export class MessageService {
  public messageList: AngularFirestoreCollection<any>;

  constructor(
    public afAuth: AngularFireAuth,
    private firestore: AngularFirestore

  ) {
    this.afAuth.authState.subscribe(user => {
      this.messageList = this.firestore.collection(
        `/posts`, ref => ref.orderBy('created')
        );
    });
  }

  getMessageList(): AngularFirestoreCollection<any> {
    return this.messageList;
  }
}

package.json

{
  "name": "pwa",
  "version": "0.0.1",
  "author": "Ionic Framework",
  "homepage": "https://ionicframework.com/",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "~8.1.2",
    "@angular/compiler": "~8.1.2",
    "@angular/core": "~8.1.2",
    "@angular/fire": "^5.2.1",
    "@angular/forms": "~8.1.2",
    "@angular/platform-browser": "~8.1.2",
    "@angular/platform-browser-dynamic": "~8.1.2",
    "@angular/pwa": "^0.803.0",
    "@angular/router": "~8.1.2",
    "@angular/service-worker": "~8.1.2",
    "@capacitor/cli": "^1.1.1",
    "@capacitor/core": "^1.1.1",
    "@ionic-native/core": "^5.0.0",
    "@ionic-native/firebase": "^5.12.0",
    "@ionic-native/splash-screen": "^5.0.0",
    "@ionic-native/status-bar": "^5.0.0",
    "@ionic/angular": "^4.7.1",
    "@ionic/pwa-elements": "^1.3.0",
    "@ionic/storage": "^2.2.0",
    "core-js": "^2.5.4",
    "firebase": "^6.4.2",
    "rxjs": "~6.3.3",
    "tslib": "^1.9.0",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/architect": "~0.801.2",
    "@angular-devkit/build-angular": "~0.801.2",
    "@angular-devkit/core": "~8.1.2",
    "@angular-devkit/schematics": "~8.1.2",
    "@angular/cli": "~8.1.2",
    "@angular/compiler": "~8.1.2",
    "@angular/compiler-cli": "~8.1.2",
    "@angular/language-service": "~8.1.2",
    "@ionic/angular-toolkit": "~2.0.0",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "~8.9.4",
    "codelyzer": "^5.0.0",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.4.3"
  },
  "description": "An Ionic project"
}

Upvotes: 0

Views: 966

Answers (2)

frido
frido

Reputation: 14089

You initialize messageList in the MessageService constructor asynchronously and its still undefined when you're calling getMessageList() in your MessagePage.

If messageList is fetched asynchronously you have to provide messageList as an Observable in some way. If you only ever need the valueChanges you can initialize an Observable that maps the authState to your collection changes. If you want / need to fetch the collection in the constructor of your Service right away you can subscribe right there and use shareReplay to supply late subscribers in your Component with the last fetched value.

public messageList: Observable<any>;

constructor(public afAuth: AngularFireAuth, private firestore: AngularFirestore) {
  this.messageList = this.afAuth.authState.pipe(
    switchMap(user => this.firestore.collection(
      `/posts`, ref => ref.orderBy('created')
    ).valueChanges()),
    shareReplay(1)
  );
  this.messageList.subscribe();
}

Upvotes: 1

ErxrilOwl
ErxrilOwl

Reputation: 79

You can convert a promise to an observable by using Rxjs, there is a function called fromPromise which converts promise to observable.

Upvotes: 1

Related Questions