likes
comments
collection
share

sentry报SyntaxError: "undefined" is not valid JSON

作者站长头像
站长
· 阅读数 14

为什么报错了

不符合JSON的数据要求。SyntaxError是在JSON.parse解析数据的时候报的错误。JSON字符串的语法定义还是比较明确的。本来我以为不符合JSON的语法就会报错的。但是在MDN看到这样的一种可能性:

let code = '"\u2028\u2029"';
JSON.parse(code); // 正常
eval(code); // 错误

所以我决定不纠结这种没有意义的事情。在业务当中,只有我们能够对undefined判空就足够了。

而且还有更多让人纠结的事情,JSON现在到底是否属于JS?MDN下面截图位置链接已经点不开。

sentry报SyntaxError: "undefined" is not valid JSON

简单了解一下它

sentry报SyntaxError: "undefined" is not valid JSON

JSON.stringifyJSON.parse 是我们常用的两个属性。我们一下场景中频繁使用:

  1. set对象数据进本地缓存中,get的时候 JSON.parse 。这是因为storage只能保存字符串。
  2. 个别后台偷懒,不想要对数据进行编译,只接受字符串,这个时候也需要前端 JSON.stringify 一遍数据。
  3. Vue由于数据的监听机制的特性,可以使用 JSON.parse(JSON.stringify(data)) 进行深拷贝,强制刷新界面

对于它们的用法,MDN已经足够全面。

JSON.parse

JSON.parse(text[, reviver])
// text: 要被解析成 JavaScript 值的字符串,关于 JSON 的语法格式
// reviver 可选: 转换器,如果传入该参数 (函数),可以用来修改解析生成的原始值,调用时机在 parse 函数返回之前。
// 返回值: Object 类型,对应给定 JSON 文本的对象/值。
// 异常: 若传入的字符串不符合 JSON 规范,则会抛出 SyntaxError 异常。

JSON.stringify

JSON.stringify(value[, replacer [, space]])
// ...

[]里面内容表示可选,逗号作为可选参数的一部分,所以也在[]之中。

从上面的API可以知道,这两个API的参数我们平时基本只用到了 text ,其他的参数,想来不知道有,更是不知道如何使用,比如说我。对于它们的具体使用,我会另开一篇文章来描述。

基本知道了它们的用处之后,我们来看看对于这样错误如何解决。

如何处理

用可选链处理

在我们业务场景下,出错的原因基本都是传进的 textnull 或者undefined 。所以我们只需要添加可选链条就可以解决了。如下:

JSON.parese(data || null)
JSON.parese(data?.name)

使用try catch

我们可以在使用JSON两个方法的时候添加try catch。如果使用的地方多,也可以简单封装一下,如下:

export function parse(str: string) {
  let value
  try {
    value = JSON.parse(str)
  } catch {
    value = null
  }
  return value
}

export function stringify(str: string) {
  let value
  try {
    value = JSON.stringify(str)
  } catch {
    value = null
  }
  return value
}

从根本上的解决问题

上面的两种方式都只是将控制台的报错给忽略了,使其不阻塞JS的运行。但是问题已经存在!

我们解决这样的问题,依旧需要高明白为什么我们的text 会是非JSON规范。会是undefined。如果是后台返回的,就让后台自省,如果是前端在处理数据的时候出的问题,就解决前端。

这才是从根本上解决问题的思路。try catch只能作为兜底操作而已,毕竟如果是后台的数据问题,人家不一定搭理你。

滥用try catch是不负责任的!try catch应该放在可预判的地方。

对于代码健壮性的讨论

SyntaxError: "undefined" is not valid JSON 就是代码不够健壮的导致的问题。它的危害极大,一旦报错了,会直接阻塞JS的运行。我们再怎么重视都不为过。

健壮的代码可以很好的避免这样的问题。但是很多时候,没有遇到之前,不一定可以考虑得那么的周全。这也是富有经验的程序员的价值,可以把一些问题拦截在生产之前。

不过终究是没有那么多的有经验的码农。

  • 所以就有了 lodash 这种库的存在;
  • 有了axios的兜底错误处理方案;
  • 有了从后端传到前端的容灾的概念;
  • 有了TS的大行其道,它在编译阶段就会给与开发者判空。

其中对于“容灾”。我们把健壮性的概念扩展到整个前端业务。那么我们前端的容灾手段也是一种增强我们的业务健壮性的一种手段。

  • localstorage缓冲接口数据
  • 利用Service worker的caches API做页面接口缓存

总结

  • 在使用parse的时候,被解析的字符串需要符合JSON规范
  • 为了全局复用,我们需要封装JSON的两个方法来提高健壮性
  • 扩展健壮性的概念,我们可以将TS、前端容灾的包括在内