【问题标题】:Why does the data from Firebase is loading just after refresh? (Angular)为什么 Firebase 的数据在刷新后立即加载? (角度)
【发布时间】:2021-04-20 16:56:51
【问题描述】:

我正在用 Angular 构建一个网站。
该站点包含一个登录页面,在用户登录后,会有一个到用户个人资料页面的路由,该页面应显示存储在 Firebase 中的数据。

由于某种原因,刷新页面后数据会立即显示在屏幕上。
您知道原因是什么,我该如何解决这个问题?

提前谢谢!

这是我认为的相关代码:

profile.component.html:

<h3 *ngFor="let item of user">Welcome back {{item.name}},</h3>
<h4>Your Details:</h4>
<table>
    <tbody *ngFor="let item of user">
        <div>
            <tr>
                <th>Name:</th>    
                <td>{{item.name}}</td>
            </tr>
            <tr>
                <th>Email:</th>   
                <td>{{item.email}}</td>
            </tr>
            <tr>
                <th>Phone Number:</th>   
                <td>{{item.phone}}</td>
            </tr>
        </div>
    </tbody> 
</table>

profile.component.ts:

import { Component, OnInit } from '@angular/core';
import {CrudService} from '../services/crud.service';
import { AuthService } from '../services/auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
  user: any;
  message = '';
  errorMessage = ''; 
  error: {name:string, message:string} = {name:'' , message:''}; //firebase error handle

  constructor(public authservice: AuthService, private router: Router,public crudservice:CrudService) { }

  ngOnInit(){
    if(this.authservice.currentUser != null)//We will make sure the user is logged in
    {
      this.crudservice.get_userInfo().subscribe(data => {
        this.user = data.map(c => {
          return {
            id: c.payload.doc.id,
            name: c.payload.doc.data()['name'],
            email: c.payload.doc.data()['email'],
            phone: c.payload.doc.data()['phone'],
          };
        })
        console.log(this.user);
      });  
    }
  }
}

auth.service.ts:

import { Injectable } from '@angular/core';
import { AngularFireAuth} from '@angular/fire/auth';
import {Router} from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  authState: any =null;
  constructor(private afu: AngularFireAuth, private router: Router) {
    this.afu.authState.subscribe((auth =>{
      this.authState = auth;
    }))
  }
  //get fanctions, to get data from firebase
  get isUserAnonymousLoggedIn(): boolean{
    return (this.authState !== null) ? this.authState.isAnonymous : false
  } 
  get currentUserId(): string{
    return (this.authState !== null) ? this.authState.uid : ''
  } 
  get currentUserName(): string{
    return this.authState['email']
  } 
  get currentUser(): any{
    return (this.authState !== null) ? this.authState : null;
  } 
  get isUserEmailLoggedIn(): boolean{
    if((this.authState !== null) && (!this.isUserAnonymousLoggedIn)){
      return true
    } else{
      return false
    }
  } 
  //function in use in login.component.ts
  loginWithEmail(email: string, password: string){
    return this.afu.signInWithEmailAndPassword(email, password)
    .then((user) => {
      this.authState = user
    }).catch(error=>{
        console.log(error)
        throw error
      })
  }
}

crud.service.ts:

import { Injectable } from '@angular/core';
import { from } from 'rxjs';
import {AngularFirestore} from '@angular/fire/firestore';
import { AuthService } from '../services/auth.service';

@Injectable({
  providedIn: 'root'
})
export class CrudService {

  constructor(private authservice: AuthService, public fireservices:AngularFirestore) { }
  
  get_userInfo()
  {
    return this.fireservices.collection('users').doc(this.authservice.currentUserId).collection('user-info').snapshotChanges();
  }
}

login.component.ts:

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../services/auth.service';
import {Router} from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  email="";
  password="";
  errorMessage = ''; //validation error handle
  error: {name:string, message:string} = {name:'' , message:''}; //firebase error handle

  constructor(private authservice: AuthService, private router: Router) { }
  
  ngOnInit(): void {
  }

  login()
  {
    this.clearErrorMessage();
    if(this.validateForm(this.email, this.password))
    {
      this.authservice.loginWithEmail(this.email, this.password)
      .then(() => {
        this.router.navigate(['/profile'])
      }).catch(_error =>{
        this.error = _error
        this.router.navigate(['/login'])
      })
    }  
  }

  clearErrorMessage()
  {
    this.errorMessage = '';
    this.error = {name: '', message:''};
  }

  validateForm(email, password)
  {
  .
  .
  .
  .
  }
}

【问题讨论】:

    标签: angular firebase firebase-realtime-database google-cloud-firestore


    【解决方案1】:

    那是因为订阅首先返回 null 或 undefined。
    要解决此问题,您的代码将如下所示:

      this.crudservice.get_userInfo().subscribe(data => {
             if(data != null && data != undefined) {
                this.user = data.map(c => {
                  return {
                    id: c.payload.doc.id,
                    name: c.payload.doc.data()['name'],
                    email: c.payload.doc.data()['email'],
                    phone: c.payload.doc.data()['phone'],
                  };
                })
                console.log(this.user); 
           }
         }
    

    您也可以在 HTML 页面中添加 ngIf

    <div *ngIf="user != null" >
    <h3 *ngFor="let item of user">Welcome back {{item.name}},</h3>
    <h4>Your Details:</h4>
    <table>
        <tbody *ngFor="let item of user">
            <div>
                <tr>
                    <th>Name:</th>    
                    <td>{{item.name}}</td>
                </tr>
                <tr>
                    <th>Email:</th>   
                    <td>{{item.email}}</td>
                </tr>
                <tr>
                    <th>Phone Number:</th>   
                    <td>{{item.phone}}</td>
                </tr>
            </div>
        </tbody> 
    </table>
    </div>
    

    更多细节在这里:

    https://rxjs-dev.firebaseapp.com/guide/subscription
    希望有用

    【讨论】:

    • 非常感谢您的回答!我根据您的建议更改了代码,但在信息加载之前我仍然需要刷新页面。这可能与我如何将登录页面导航到个人资料页面有关吗? (我在问题中添加了 login.component.ts 代码)
    • 您有没有假设问题可能出在哪里? @A.khalifa
    • 我认为this.authservice.currentUser
    • 尝试删除这段代码 if(this.authservice.currentUser != null)//我们会确保用户已经登录
    • 谢谢@A.khalifa,我删除了这行,但问题依旧
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2021-10-30
    • 2016-04-28
    • 1970-01-01
    • 2017-09-20
    相关资源
    最近更新 更多