Angular集成Firebase报错:Cannot read property 'uid' of null 求助
解决Firebase
TypeError: Cannot read property 'uid' of null 问题 嘿,我来帮你搞定这个问题~你遇到的这个错误,核心原因是你的Angular服务初始化时,Firebase的用户认证状态还没加载完成,导致firebase.auth().currentUser返回了null,这时候去访问它的uid属性就会触发报错。虽然功能能正常运行,但这个错误是服务启动时机和Firebase认证加载时机不匹配导致的。
问题出在哪?
看你的CategoriesListService代码,你在类的顶部直接赋值currentUser = firebase.auth().currentUser,但Angular服务启动的速度比Firebase认证状态加载的速度快,这时候currentUser还没拿到用户数据,就是null,自然读不了uid咯。
具体解决方案
我们可以通过监听Firebase的用户认证状态变化,确保拿到有效用户后再初始化数据库引用。修改你的服务代码如下:
import { Injectable } from '@angular/core'; import { AngularFireDatabase } from 'angularfire2/database'; import { Item } from '../models/item.model'; import * as firebase from 'firebase'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/switchMap'; @Injectable() export class CategoriesListService { // 先声明变量,不直接初始化 private categoriesListRef; constructor(private db: AngularFireDatabase) { // 监听用户登录/登出状态变化 firebase.auth().onAuthStateChanged(user => { if (user) { // 只有当用户登录成功后,才创建数据库引用 this.categoriesListRef = this.db.list<Item>(`categories-list/${user.uid}`); } }); } getCategoriesList() { // 这里用authState来动态获取用户,确保每次调用都有有效用户 return firebase.auth().authState.switchMap(user => { if (user) { return this.db.list<Item>(`categories-list/${user.uid}`); } else { // 用户未登录时返回空的Observable,避免报错 return Observable.of(null); } }); } addItem(item: Item) { const currentUser = firebase.auth().currentUser; if (currentUser) { // 每次添加时都动态获取当前用户的数据库引用 return this.db.list<Item>(`categories-list/${currentUser.uid}`).push(item); } else { throw new Error('请先登录再添加数据哦~'); } } editItem(item: Item) { const currentUser = firebase.auth().currentUser; if (currentUser && item.key) { return this.db.list<Item>(`categories-list/${currentUser.uid}`).update(item.key, item); } else { throw new Error('用户未登录或待编辑的条目无效'); } } removeItem(item: Item) { const currentUser = firebase.auth().currentUser; if (currentUser && item.key) { return this.db.list<Item>(`categories-list/${currentUser.uid}`).remove(item.key); } else { throw new Error('用户未登录或待删除的条目无效'); } } }
这样改的好处
- 彻底避免初始化时的null错误:不再在服务启动时硬拿
currentUser,而是等Firebase确认用户登录后再创建数据库引用。 - 适配用户状态变化:比如用户登出后再登录,代码会自动更新数据库引用,不会出现旧引用失效的问题。
- 增加友好的错误提示:添加了用户未登录时的错误抛出,方便你调试和给用户提示。
对应的HomePage代码调整
因为getCategoriesList现在返回的是Observable,你需要稍微调整HomePage里的代码来适配:
import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { CategoriesListService } from '../../services/categories-list.service'; import { Observable } from 'rxjs/Observable'; import { Item } from './../../models/item.model'; import 'rxjs/add/operator/switchMap'; @IonicPage() @Component({ selector: 'page-home', templateUrl: 'home.html', }) export class HomePage { categoriesList$: Observable<Item[]>; constructor( public navCtrl: NavController, public navParams: NavParams, private categories: CategoriesListService ) { this.categoriesList$ = this.categories.getCategoriesList() .switchMap(list => { if (list) { return list.snapshotChanges().map(changes => { return changes.map(c => ({ key: c.payload.key, ...c.payload.val() })); }); } else { // 用户未登录时返回空数组 return Observable.of([]); } }); } ionViewDidLoad() { console.log('ionViewDidLoad HomePage'); } }
这样调整后,不仅能解决你遇到的错误,还能让代码更健壮,适配用户登录状态的变化~
内容的提问来源于stack exchange,提问作者Aneeque Ahmed
相关产品推荐
相关产品推荐

