Firebase - Current User insider Provider

Hello guys,

In some places of my app I already get the current logged using:

firebase.auth().currentUser.uid

I’m trying to do the same inside a provider class:

@Injectable()
export class SmartAudioProvider {

    audioType: string = 'html5';
    sounds: any = [];



    user : User ={
        id : firebase.auth().currentUser.uid
      }

    constructor(
        public nativeAudio: NativeAudio,
        platform: Platform,

Maybe something with lifecycle.

Does anyone have any clue of what I’m doing wrong?

Thank you!!! :slight_smile:

import { Injectable, OnInit } from '@angular/core';
import { NativeAudio } from '@ionic-native/native-audio';
import { Platform } from 'ionic-angular';
import { User } from '../../model/user.model';
import * as firebase from 'firebase/app';
import { UserServicesProvider } from '../user-services/user-services';


@Injectable()
export class SmartAudioProvider {

    audioType: string = 'html5';
    sounds: any = [];



    user : User ={
        id : firebase.auth().currentUser.uid
      }

    constructor(
        public nativeAudio: NativeAudio,
        platform: Platform,
        public userServicesProvider: UserServicesProvider) {


        if (platform.is('cordova')) {
            this.audioType = 'native';
        }


    }

    preload(key, asset) {

        if (this.audioType === 'html5') {

            let audio = {
                key: key,
                asset: asset,
                type: 'html5'
            };

            this.sounds.push(audio);

        } else {

            this.nativeAudio.preloadSimple(key, asset);

            let audio = {
                key: key,
                asset: key,
                type: 'native'
            };

            this.sounds.push(audio);
        }

    }

    play(key) {


        if (!this.user) {
            console.log('USUARIO NULL ');
            //error here
            this.user.id = firebase.auth().currentUser.uid;
            this.userServicesProvider.getById(this.user.id).subscribe(res => {
                this.user = res
                this.playSound(key);
            });
    
        }

        

    }

    playSound(key){
        if (!this.user.soundOn) { return };

        let audio = this.sounds.find((sound) => {
            return sound.key === key;
        });

        if (audio.type === 'html5') {

            let audioAsset = new Audio(audio.asset);
            audioAsset.play();

        } else {

            this.nativeAudio.play(audio.asset).then((res) => {
                console.log(res);
            }, (err) => {
                console.log(err);
            });

        }
    }

}

I’ve never used Firebase, but there has got to be an Angular-friendly shim for it (that should solve all of these sorts of lifecycle dependency issues with no effort on your part). Why aren’t you using it?

Hello…I’m new at angular(ionic asswell)…never used and ‘Angular-friendly shim’. I will research about it . Thank you

I’m not sure about beeing a lifecycle problem… in another class it works, but is a page…not a provider

@IonicPage()
@Component({
  selector: 'page-my-matches',
  templateUrl: 'my-matches.html',
})
export class MyMatchesPage {

  user : User ={
    id : firebase.auth().currentUser.uid
  }

I would start here.

When you’re calling things that are unaware of Angular’s DI management, such as the way you’re accessing firebase as a global, then you take the responsibility for ensuring that everything is set up properly for them. If, as you say, you’re new to Angular in general, that is going to be a very daunting ask, and I would recommend trying to stick with searching out Angular-friendly interfaces to everything you work with, which basically just means that people familiar with Angular have done all the tedious difficult work and stuff will just more or less work the way you would expect it to.

1 Like

AngularFire is the thing. However, it’s a bit controversial, based on conversations I’ve had here, and issues I’ve seen on the AF github. If someone wants to use Firebase the way they’d use MongoDB – long term storage, no “real time” anything – it’s probably just better to use the Firebase SDK in an Angular provider you write yourself, exposing only the three commands (or whatever) your app will need. AngularFire becomes critical if using Firebase for a chat program or similar.

Hey there,

I would 100% use AngularFire2 if I’m building an app with either Angular or @ionic/angular. But that’s not going to solve your problem here.

The problem is that firebase.auth().currentUser.uid is a synchronous operation, meaning that it tries to get the value right then and there and assign it to whatever it is you want to assign it.

It works on some of your pages because those pages aren’t being called on app load, so the function has time to resolve the user before assigning it to the id property.

It’s not working on your provider because (I’m guessing) you’re calling it on app load, so when it does firebase.auth().currentUser.uid the user isn’t resolved yet, even if there’s an actual user logged in.

Firebase provides another function to get the user, the function is called onAuthStateChanged() you can find the docs here.

You call the function and then get the user inside of it.

firebase.auth.onAuthStateChanged( user => {
  // Here you can access the user object with all of their data.
});

Hope this helps and do let me know if you have any questions about how it works.

2 Likes

Fair enough. Can we agree, though, that for OP, given their self-declared lack of experience, that writing a suitable Angular provider is probably not a viable option?

Sure, but for example: Do we need Angularfire2?

Hello, sorry guys… took to long to get back to coding… i’ve tryed to do as you told me but it seens that the firebase lib that i’m using doen’t have the method…

import * as firebase from 'firebase/app';

I trying to find a similar one.

javebratt thank you for the great explanation!

Sorry! It DOES work as u said! Thank you!!!

1 Like

No problem, glad I could help :slight_smile: