使用Firebase注册用户时触发Maximum call size exceeded错误排查
我正在使用Firebase为网站搭建用户认证功能,认证环节可正常运行。但用户注册成功后,想向Firebase Realtime Database写入该用户的额外信息(Firebase Auth仅支持邮箱和密码字段)。
认证成功后调用的registerUser(uid)函数如下:
function registerUser(uid) { const db = getDatabase(); var name = document.getElementById('firstName').value; var surname = document.getElementById('lastName').value; var email = document.getElementById('email').value; var category = document.querySelector('.category').lastChild; var categoryText = category.options[category.selectedIndex].text; var utente; if (categoryText === "Studente") { utente = new Studente(name, surname, email); const utenteJSON = JSON.stringify(utente); set(ref(db, "Users/" + uid), { Studente: utenteJSON, }) .then(() => { window.location.href = "viewInserisciMetodoPagamento.html"; }) .catch((error) => { alert(error); }) } else { console.log("shown"); utente = new Ascoltatore(name, surname, email); console.log("not shown"); const utenteJSON = JSON.stringify(utente); set(ref(db, "Users/" + uid), { Ascoltatore: utenteJSON, }) .then(() => { window.location.href = "viewInserisciMetodoPagamento.html"; }) .catch((error) => { alert(error); }) } }
问题仅在用户注册时选择“Ascoltatore”类别时出现:else分支中,代码执行到utente = new Ascoltatore(name, surname, email)后便停止运行。
Ascoltatore是自定义的用户数据存储类,Studente类代码如下(两者结构类似):
import User from './User.js'; export default class Studente extends User { constructor(firstName, lastName, email, metodiPagamento = [], titoliStudioList = [], /*materieCompetenzaList = []*/) { super(firstName, lastName, email, metodiPagamento); this._titoliStudioList = titoliStudioList; /*this._materieCompetenzaList = materieCompetenzaList;*/ } get titoliStudioList() { return this._titoliStudioList; } set titoliStudioList(titoloStudio) { this._titoliStudioList.push(titoloStudio); } /* get _materieCompetenzaList() { return this._materieCompetenzaList; } set _materieCompetenzaList(materia) { this._materieCompetenzaList.push(materia); }*/ }
当注释掉materieCompetenzaList相关字段时,流程正常运行;启用该字段时触发“Maximum call size exceeded”错误,请问原因是什么?
这个错误的核心是JSON.stringify序列化类实例时触发了无限递归,具体原因如下:
getter命名错误导致递归死循环
你启用的_materieCompetenzaListgetter,命名和私有属性this._materieCompetenzaList完全一致。当JSON.stringify尝试读取这个属性时,会调用getter函数,而getter又返回this._materieCompetenzaList,这会再次触发getter调用,形成无限递归,最终超出调用栈大小,抛出错误。Ascoltatore类触发问题的原因
Studente类中你注释了_materieCompetenzaList的getter/setter,而Ascoltatore类中保留了这个错误的getter定义,所以实例化Ascoltatore后执行JSON.stringify(utente)时,直接触发了递归死循环。
解决步骤
- 修正getter命名:把getter的名字改成不带下划线的
materieCompetenzaList,和其他属性(比如titoliStudioList)的命名规则保持一致:
get materieCompetenzaList() { return this._materieCompetenzaList; } set materieCompetenzaList(materia) { this._materieCompetenzaList.push(materia); }
这样JSON.stringify序列化时会正确调用getter获取属性值,不会触发无限递归。
- 额外优化建议:如果想更精准控制JSON输出,可以在类中定义
toJSON方法,手动指定要序列化的属性,避免自动遍历所有getter的问题:
toJSON() { return { firstName: this._firstName, // 需根据User类的私有属性名调整 lastName: this._lastName, email: this._email, metodiPagamento: this._metodiPagamento, materieCompetenzaList: this._materieCompetenzaList }; }
JSON.stringify会优先调用这个方法,直接返回纯数据对象,彻底避免getter递归的问题。
内容的提问来源于stack exchange,提问作者chiagger

