Firebase数据库ref.on()无响应及replace调用报错求助
解决你的Firebase评语系统问题
看起来你遇到的核心问题是异步操作处理不当加上一个变量名拼写错误,这两个问题直接导致了函数无响应和undefined报错。咱们一步步来修复:
问题1:变量名拼写错误
在表格生成代码里,你调用了stdRemarks(stdnameName),但前面定义的学生名字变量是stdiName(注意是stdi而非stdname),这个笔误会导致传入undefined给stdRemarks,自然返回undefined,进而触发replace的调用错误。先把这个变量名改对:
${stdRemarks(stdiName).replace(/undefined/g, '')}
问题2:异步回调导致stdRemarks返回undefined
Firebase的ref.on("value")是异步操作,当你在stdRemarks里调用它时,函数会立刻返回初始的finalStuff(也就是undefined),而回调函数里的逻辑要等Firebase返回数据后才会执行,这时候return已经无法影响函数的返回值了。
我们需要把stdRemarks改成异步函数,用once("value")(因为你只需要获取一次数据,不需要实时监听变化)配合async/await来处理,这样就能正确拿到返回值:
重构后的stdRemarks函数
async function stdRemarks(studentName){ let finalStuff = ""; // 初始化空字符串,避免undefined拼接出无效内容 const snapshot = await ref.once("value"); // 单次获取数据,等待结果返回 // 用可选链避免路径不存在时报错 const remarks = snapshot.val().schools[returnCurrentUser()][studentName]?.['remarks']; if (!remarks) return ""; // 如果没有评语,直接返回空字符串 const keys = Object.keys(remarks); for(let i=0;i<keys.length;i++){ // 用let声明i,避免全局变量污染 const objectToDealWith = remarks; const remark = objectToDealWith[keys[i]]['remark'] || ""; const examiner = objectToDealWith[keys[i]]['examiner'] || ""; const fullRemark = ` ${examiner}: ${remark} | `; finalStuff += fullRemark; } // 去掉最后多余的" | ",避免末尾残留无效符号 return finalStuff.slice(0, -3) || ""; }
修改表格生成代码(适配异步函数)
原来的表格生成代码在ref.on("value")的回调里,我们把这个回调改成async函数,这样就能await stdRemarks的结果:
ref.on("value", async function(snapshot){ // 加上async关键字 let dashTab = document.getElementById("dashboard_table"); let btn = document.getElementById("csv_blob"); let btn2 = document.getElementById("json_view"); let btn3 = document.getElementById("json_export"); btn.style.display = "block"; btn2.style.display = "block"; $("#json_export").css('display', 'block'); dashTab.innerHTML = "<thead><tr><th>Student Name</th><th>Class</th><th>Email</th><th>Subject</th><th>Project Info</th><th>Remarks</th><th>Project</th><th style='display: none;'>Project Download URL</th><th>Add Remark</th></tr></thead>"; let jsonRecieved = snapshot.val(); let objectToDealWith = snapshot.val().schools[returnCurrentUser()]; // 替换非标准的Object.size,改用标准的Object.keys().length let names = Object.keys(objectToDealWith); let lengthOfIt = names.length; // 注意:这里的objectToDealWith['i']看起来可能是笔误,建议替换为实际的学校名称字段 document.getElementById("schoolnameis").innerText = "Dashboard - " + objectToDealWith['i']; for(let i=0;i<lengthOfIt;i++){ // 用let声明i,避免全局变量污染 let int = i + 1; let stdName = names[i]; let finalResult = objectToDealWith[stdName]; // 给字段默认值,避免undefined出现 let stdClass = finalResult['class'] || ""; let stdEmail = finalResult['email'] || ""; let stdSubject = finalResult['subject'] || ""; let stdiName = finalResult['stdname'] || ""; let stdProjectName = finalResult['projectname'] || ""; let stdProjectInfo = finalResult['projectinfo'] || ""; let stdProjectLink = finalResult['projectlink'] || "#"; // 等待stdRemarks返回结果 let studentRemarks = await stdRemarks(stdiName); // 现在可以安全调用replace,因为studentRemarks不会是undefined let cleanedRemarks = studentRemarks.replace(/undefined/g, ''); let elementToPush = `<tr><td>${stdiName.replace(/undefined/g, '')}</td><td>${stdClass.replace(/undefined/g, '')}</td><td>${stdEmail.replace(/undefined/g, '')}</td><td>${stdSubject.replace(/undefined/g, '')}</td><td>${stdProjectInfo.replace(/undefined/g, '')}</td><td>${cleanedRemarks}</td><td><a href=${stdProjectLink}>${stdProjectName.replace(/undefined/g, '')}</a></td><td style='display:none;'>${stdProjectLink}</td><td id="${stdName}" style='text-align:center;' onclick="closeThatSomeThing();getIdOfTd(this.id)">➕</td></tr>`; dashTab.innerHTML += elementToPush; } });
额外小优化说明
- 初始化
finalStuff为空字符串,避免一开始就是undefined导致拼接出undefinedxxx这类无效内容 - 用可选链操作符
?.避免路径不存在时报错 - 给所有字段加上
|| ""默认值,减少undefined的出现,降低replace的使用频率 - 替换非标准的
Object.size为Object.keys().length,保证代码兼容性
这样修改后,你的两个问题应该都能解决了,祝项目顺利提交!
内容的提问来源于stack exchange,提问作者SWAGBEAST Developers
相关产品推荐
相关产品推荐

