如何判断Firebase对应数据是否存在并作为业务逻辑执行条件
问题根因
Firebase Realtime Database 的 once('value') 方法只有在请求本身失败时(比如无访问权限、网络异常、参数非法)才会抛出异常触发catch。如果请求正常发送且服务端返回了结果,哪怕目标节点不存在,也会正常返回快照对象,此时 snapshot.val() 会返回null,不会触发异常,这就是你代码走不到catch分支的核心原因。
最优解决方案
Firebase 官方提供了 snapshot.exists() 方法专门用来判断目标节点是否存在,该方法仅校验节点是否有有效值,不会下载额外数据,完全符合你不下载全量数据的安全要求,同时比直接判断val() === null更严谨(避免节点存储0、false等假值时出现误判)。
你可以选择两种实现方式:
方式1:修改getUserDict,节点不存在时主动抛出异常
async function getUserDict() { const current_user_id = firebase.auth().currentUser.uid const snapshot = await firebase.database() .ref() .child('profile') .child(current_user_id) .child('user_dict') .once('value') // 节点不存在时主动抛错,触发外层catch if (!snapshot.exists()) { throw new Error('USER_DICT_NOT_EXIST') } return snapshot.val() }
修改后你原有userLogin的try/catch逻辑即可正常触发。
方式2:不修改getUserDict,直接在调用侧判断结果
如果你不想改动getUserDict的原有逻辑,也可以在try块内拿到返回结果后主动判断:
async function userLogin() { traceFunction() console.log('userLogin') if (checkLogin()) { console.log('userLogin checkLogin is true') hideInputText() left_button.style.visibility = 'hidden' showLogoAnimation() try { const user_dict = await getUserDict(); // 新增判断逻辑 if (user_dict === null) { throw new Error('USER_DICT_NOT_EXIST') } console.log('userLogin user_dict is ', user_dict) hideLogoAnimation() handleWelcome(is_first_time = false) } catch (error) { console.log('userLogin unable to find user_dict, preparing needed data') // 建议这里也用await替代链式then,避免打印的user_dict是Promise对象 const user_dict = await getQuestions() await createProfile(user_dict) console.log('userLogin user_dict is ', user_dict) hideLogoAnimation() handleWelcome(is_first_time = true) } } else { console.log('userLogin checkLogin is false') question_text.innerText = "What's your e-mail address?" showInputText() left_button.style.visibility = 'hidden' right_button.innerText = 'Submit' right_button.onclick = userSubmitEmail } }
内容的提问来源于stack exchange,提问作者user12810571
相关产品推荐
相关产品推荐

