如何将onAuthStateChanged内的用户UID传递到外部变量?
问题根源
你的代码核心问题是异步执行顺序错误:
onAuthStateChanged是异步触发的回调函数,它不会阻塞后续代码运行。- 你写的
getDoc会在UserUid被赋值之前就执行,所以此时UserUid还是初始的空字符串,自然查不到数据。
解决方案
方案1:将Firestore查询逻辑移到Auth回调内
直接把获取文档和赋值的逻辑放到 onAuthStateChanged 的回调里,确保拿到用户UID后再执行查询:
import { getDoc, doc } from 'firebase/firestore' import { onAuthStateChanged } from 'firebase/auth' interface DataUser { FullName: string; Email: string; ContactNo: string; CountryCode: string; ICNO: string; HomeAddress: string; image: string; userType: number; } // 初始化空数据,后续赋值 export let DataUser: Partial<DataUser> = {}; onAuthStateChanged(auth, async (user) => { if (user != null) { const userUid = user.uid; // 拿到UID后执行Firestore查询 const docSnap = await getDoc(doc(db, "User", userUid)); if (docSnap.exists()) { DataUser = { FullName: docSnap.data()["Name"], Email: docSnap.data()["Email"], ContactNo: docSnap.data()["Contact"], CountryCode: docSnap.data()["CountryCode"], ICNO: docSnap.data()["ICNO"], HomeAddress: docSnap.data()["HomeAddress"], image: docSnap.data()["Image"], userType: 0, }; } else { console.log("用户文档不存在"); } } else { console.log("用户未登录"); DataUser = {}; } })
方案2:用Promise封装Auth状态监听(适合async/await场景)
如果希望用更清晰的async/await语法,可以把onAuthStateChanged封装成Promise:
import { getDoc, doc } from 'firebase/firestore' import { onAuthStateChanged, User } from 'firebase/auth' interface DataUser { FullName: string; Email: string; ContactNo: string; CountryCode: string; ICNO: string; HomeAddress: string; image: string; userType: number; } // 封装Auth状态监听为Promise function waitForAuth(): Promise<User | null> { return new Promise((resolve) => { const unsubscribe = onAuthStateChanged(auth, (user) => { resolve(user); unsubscribe(); // 拿到用户后取消监听,避免重复触发 }); }); } // 加载用户数据的异步函数 async function loadUserData() { const user = await waitForAuth(); if (!user) { console.log("用户未登录"); return null; } const docSnap = await getDoc(doc(db, "User", user.uid)); if (!docSnap.exists()) { console.log("用户文档不存在"); return null; } return { FullName: docSnap.data()["Name"], Email: docSnap.data()["Email"], ContactNo: docSnap.data()["Contact"], CountryCode: docSnap.data()["CountryCode"], ICNO: docSnap.data()["ICNO"], HomeAddress: docSnap.data()["HomeAddress"], image: docSnap.data()["Image"], userType: 0, } as DataUser; } // 导出加载函数,在需要的地方调用 export { loadUserData };
额外注意点
- 你之前尝试用
this.UserUid报错,是因为普通函数回调里this的指向不符合预期,这里根本不需要用this,解决异步顺序问题即可。 - 必须处理文档不存在的情况,避免
docSnap.data()!强制非空导致的运行时错误。 - 如果是React/Vue等框架项目,建议用框架的状态管理(比如React的
useState+useEffect)存储用户数据,更符合响应式逻辑。
内容的提问来源于stack exchange,提问作者Dante How
相关产品推荐
相关产品推荐

