问题:
今天在复习uni-app项目,使用Vuex时展示购物车数据,HbuilderX编译通过,但是小程序的界面就是加载不出来,并且同项目的安卓模拟器可以正常显示。小程序报错: SyntaxError: Unexpected end of JSON input
问题截图:
分析过程:
1.小程序页面显示错误,但是安卓正常显示,这样导致分析起来有点困难,确实不知该从何下手
2.后来清了下缓存,微信开发者工具提示了图中的报错,看意思可以知道是没有正常读取到JSON数据。
我在Vuex中当前购物车所使用的的state数据如下:
export default {
namespaced:true,
state:()=>({
// { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state }
//写入了本地,所以需要调用Json.stringfy方法去读取,并且要为空时应该给予一个空数组
cart: JSON.parse(uni.getStorageSync('cart')) || []
}),
3.可以看到我主要使用了一个cart对象,本意是想读取本地缓存中的cart字段并去JSON化,从而方便后续使用,如果读取不到时就给一个空数组对象,这样页面也不会有异常
4.一开始使用AI分析时,它建议我将结构进行如下修改:
let cart;
try {
cart = JSON.parse(uni.getStorageSync('cart'));
} catch (e) {
cart = [];
}
// 然后可以将 cart 赋值给对象的属性,或者在其他地方使用它
const myObject = { cart };
问题在于第一次写项目时没有这么复杂,但是逻辑就是我上方所表达的逻辑,只能继续思考表达式错在了哪里
解决方法:
后面重新查看了项目文档,将源代码复制过来,运行正常了…
修改后的代码片段如下:
export default {
namespaced:true,
state:()=>({
// { goods_id, goods_name, goods_price, goods_count, goods_small_logo, goods_state }
//写入了本地,所以需要调用Json.stringfy方法去读取,并且要为空时应该给予一个空数组
//错误写法
//cart: JSON.parse(uni.getStorageSync('cart')) || []
//改正写法
cart: JSON.parse(uni.getStorageSync('cart') || '[]')
}),
可以看到修改后的cart是将空数组对象设置为一个字符串,并且放在了JSON.parse方法里面,在JSON.parse方法中使用短路运算符判断,如果解析不到本地存储中的cart字段,就将字符串格式的空数组去解析。逻辑思路和我上文中理解的一样,后面理解到了我的错误写法的问题所在:
如果我重置了缓存,像上方的错误写法,就会出现uni.getStorageSync方法读取不到cart值从而返回undefined值,JSON.parse方法再去解析undefined值就会报错。而一开始,如果本地存储中有cart这个字段,那么这个语法Bug就不会触发,而我第一遍写完该项目后又重新写的时候,在安卓模拟器中本地缓存中还是有cart对象的残留,这也就解释了一开始小程序显示异常,安卓显示正常的问题。
最后,为了确保自己的理论分析是对的,我打开了微信开发者工具,首先清除了本地缓存,然后执行如下测试:
结果与理论分析一致。并且可以从最后一个测试结果看到,如果不将空数组对象设为一个 ** ‘[]’ ** ,而是一个 [ ] 放在JSON.parse方法中,一样会导致JSON.parse方法报错。到此,这个问题就算分析结束了。
总结
本次引起的错误,主要还是对JSON.parse方法使用了解的比较生疏导致语法书写错误所致,JSON.parse() 方法的参数必须是一个有效的 JSON 字符串,否则会抛出 SyntaxError,所以如果使用短路运算表达式的时候,应注意将一个空的字符串形式的数组对象放在方法体中。