服务器的日志中经常会看到以下异常日志:

typescriptCopy code
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
Ignoring BEFORE_APP_SERIALIZED Exception: TypeError: Converting circular structure to JSON --> starting at object with constructor 'Object' | property 'children' -> object with constructor 'Array' | index 0 -> object with constructor 'Object' --- property 'parent' closes the circle at JSON.stringify (<anonymous>) at TransferState.toJson (/.../ifuyun.com/dist/server/main.js:1:4655830) at /.../ifuyun.com/dist/server/main.js:1:5349426 at /...ifuyun.com/dist/server/main.js:1:5350617 at _ZoneDelegate2.invoke (/.../ifuyun.com/dist/server/main.js:1:2306479) at Zone3.run (/.../ifuyun.com/dist/server/main.js:1:2298814) at /.../ifuyun.com/dist/server/main.js:1:2326026 at _ZoneDelegate2.invokeTask (/.../ifuyun.com/dist/server/main.js:1:2307417) at Zone3.runTask (/.../ifuyun.com/dist/server/main.js:1:2299899) at drainMicroTaskQueue (/.../ifuyun.com/dist/server/main.js:1:2311188)
Ignoring BEFORE_APP_SERIALIZED Exception: TypeError: Converting circular structure to JSON --> starting at object with constructor 'Object' | property 'children' -> object with constructor 'Array' | index 0 -> object with constructor 'Object' --- property 'parent' closes the circle at JSON.stringify () at TransferState.toJson (/.../ifuyun.com/dist/server/main.js:1:4655830) at /.../ifuyun.com/dist/server/main.js:1:5349426 at /...ifuyun.com/dist/server/main.js:1:5350617 at _ZoneDelegate2.invoke (/.../ifuyun.com/dist/server/main.js:1:2306479) at Zone3.run (/.../ifuyun.com/dist/server/main.js:1:2298814) at /.../ifuyun.com/dist/server/main.js:1:2326026 at _ZoneDelegate2.invokeTask (/.../ifuyun.com/dist/server/main.js:1:2307417) at Zone3.runTask (/.../ifuyun.com/dist/server/main.js:1:2299899) at drainMicroTaskQueue (/.../ifuyun.com/dist/server/main.js:1:2311188)

对于这样的日志,真是一头雾水,以至拖了一个多月……

今天,不想在日志中再看到此类信息,也隐隐觉得必然是代码中出现了什么问题,便想着必须要解决它……

然而,异常的发生却是间歇性、偶发的,更头疼的是,本地开发环境下,始终是正常的,而服务器SSR的日志并没有记录时间、User-Agent、URL等关键信息,甚至连异常发生的具体位置也无法定位,如以上信息所示,main.js是构建后的压缩文件,对问题的定位压根没有任何帮助。

无奈,只能在上述压缩混淆后的文件中手动加上console日志语句,等着异常再次发生……

似乎体会到了“守株待兔”的被动、无助的感觉……😒

所幸,一天之后,终于在日志文件中找到了蛛丝马迹。

根据日志的参数,定位到异常是在访问某篇文章时产生,再进行对比、排除法,可知是由评论列表导致的,如此,便可以定位到具体的代码块了。

然而,还是too young too simple了……

根据异常描述,大致是循环引用问题,因此,初步判断是递归所导致。一顿排查下来,然并卵……┓( ´∀` )┏

无奈,继续查找……在一个角落里,发现了下面这句:

typescriptCopy code
  • 1
item.children.forEach((child) => child.parent = item);
item.children.forEach((child) => child.parent = item);

在不需要序列化browser端,自然是没问题的,然而,在server端,数据是需要序列化之后进行缓存的,因此,便报错了……

知道了源头之后,解决就相对容易了……改成如下即可去除循环引用(注意:扩展运算符...无效):

typescriptCopy code
  • 1
item.children.forEach((child) => child.parent = cloneDeep(item));
item.children.forEach((child) => child.parent = cloneDeep(item));

测试,完美!┓( ´∀` )┏