如何在获取Firebase用户信息后再执行JavaScript函数?
解决方案:调整代码结构确保用户认证后再初始化jsGrid并加载数据
核心问题分析
- 页面DOM加载完成后立即初始化jsGrid,此时用户认证流程可能还未完成,导致
getData无法获取用户相关权限或数据。 _db被包裹在自执行函数内部,属于局部变量,全局环境无法直接访问;若将onAuthStateChanged放入该函数块,又会因作用域或执行顺序问题导致_db未被正确识别。
具体调整步骤
1. 重构index.js:以认证状态为核心驱动,修复作用域问题
调整Firebase初始化、认证监听和数据逻辑的顺序,将_db改为全局可访问的变量,确保只有用户登录后才初始化数据控制器:
// 先初始化Firebase核心实例 const firebaseConfig = { // 填写你的Firebase配置信息 }; const app = initializeApp(firebaseConfig); const auth = getAuth(app); const db = getFirestore(app); const db_name = "tesint"; const collectionRef = collection(db, db_name); // 全局声明_db,后续在认证完成后赋值 let _db; async function getData(filter) { // 先校验用户登录状态 const user = auth.currentUser; if (!user) throw new Error("用户未登录,无法获取数据"); // 你的数据查询逻辑,可结合filter和用户信息(如user.uid)过滤数据 const querySnapshot = await getDocs(collectionRef); return querySnapshot.docs.map(doc => ({ ...doc.data(), uid: doc.id })); } // 监听用户认证状态变化,这是核心触发点 onAuthStateChanged(auth, (user) => { if (user) { console.log('用户已登录'); // 用户登录后才初始化数据控制器 _db = { loadData: function(filter) { return getData(filter); } }; // 触发jsGrid初始化 initJsGrid(); } else { console.log('用户未登录'); // 未登录时隐藏表格或提示登录 if ($("#jsGrid").length) { $("#jsGrid").hide(); } } }); // 登录/登出按钮逻辑 const provider = new GoogleAuthProvider(); const signInBtn = document.getElementById("signInBtn"); const signOutBtn = document.getElementById("signOutBtn"); signInBtn.onclick = () => { signInWithPopup(auth, provider) .then((result) => { console.log('登录成功:', result.user); }) .catch((error) => { console.error('登录失败:', error); alert(`登录错误:${error.message}`); }); }; signOutBtn.onclick = () => { signOut(auth).then(() => { console.log('用户已登出'); $("#jsGrid").hide(); }); }; // 暴露全局函数,供认证回调触发jsGrid初始化 window.initJsGrid = function() { $("#jsGrid").jsGrid({ width: "100%", height: "90%", heading: true, insertRowLocation: "top", loadMessage: "请稍候...", noDataContent: "暂无数据,请尝试刷新", filtering: true, editing: true, inserting: true, sorting: false, paging: true, autoload: true, confirmDeleting: true, pageSize: 15, pageButtonCount: 5, pageLoading: true, deleteConfirm: "确定要删除这行吗?", controller: _db, fields: [ { name: "name", type: "text", width: 150 }, { name: "uid", type: "number", width: 200 }, { type: "control", align: "center"} ] }); $("#jsGrid").show(); };
2. 修改index.html:移除提前初始化逻辑,等待认证触发
删除原来DOM加载时立即初始化jsGrid的代码,改为等待用户登录后通过全局函数触发:
<!DOCTYPE html> <html> <head> <!-- 先引入依赖库 --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid-theme.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jsgrid/1.5.3/jsgrid.min.js"></script> <!-- 引入Firebase SDK --> <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-auth-compat.js"></script> <script src="https://www.gstatic.com/firebasejs/9.23.0/firebase-firestore-compat.js"></script> <script src="./index.js"></script> </head> <body class="myclass"> <!-- 登录/登出按钮 --> <button id="signInBtn">登录</button> <button id="signOutBtn">登出</button> <!-- jsGrid容器,默认隐藏 --> <div id="jsGrid" style="display:none;"></div> </body> </html>
关键调整说明
- 认证优先:通过
onAuthStateChanged监听用户状态,确保只有登录后才初始化数据控制器和表格,避免未认证时调用数据接口。 - 作用域修复:将
_db改为全局变量,在认证回调中赋值,彻底解决局部作用域无法访问的问题。 - 延迟初始化:jsGrid不再随DOM加载自动初始化,而是等待用户登录后触发,从根源避免了数据加载与认证不同步的问题。
内容的提问来源于stack exchange,提问作者Mohit H
相关产品推荐
相关产品推荐

