提出问题
下面的代码在有初始值的情况下,能够工作的很好,但是当localStorage
中存在非法的数据时就会抛出异常,如果你的程序没有做好异常处理,就会崩溃。
const todosStr = localStorage.getItem('todos')
const todos = JSON.parse(todosStr)
分析问题
能够抛出异常的位置在JSON.parse
,当JSON.parse
解析的内容为以下情况时,就会抛出异常:
1 传参是无效的json
字符串
JSON.parse("{name: 'John'}");
// Uncaught SyntaxError: Expected property name or '}' in JSON at position 1 (line 1 column 2)
JSON.parse('')
// Uncaught SyntaxError: Unexpected end of JSON input
2 解析的内容是undefined
JSON.parse(undefined)
// Uncaught SyntaxError: Unexpected end of JSON input
解决问题
知道了JSON.parse
可能会抛出异常,我们在使用localStorage
时做一下异常处理:
function getFromLocalStorage(key) {
try {
return JSON.parse(localStorage.getItem(key));
} catch (error) {
console.error(`Error parsing data from localStorage key "${key}": ${error}`);
return null;
}
}
我们在异常发生的时候,返回了null
,getItem
在获取不到数据时也是返回null
,这样用户就可以平滑的做空处理。
const todos = getFromLocalStorage('todos') || [];
总结问题
1 只做最关键的工作
我们没有在localStorage.getItem('todos')
处做额外的异常处理和空判断,因为问题的源头发生在JSON.parse
处。
2 保持接口的一致性
我们在异常处理时,与getItem
保持了一致的返回值,这样在调用处就不用担心意料之外的情况发生。
3 只封装不可变的部分
我们没有将空判断放到函数里面,因为这是可变的部分,目标数据可能是字符串,也可能是数组,如果封装到内部就不够灵活了。相反,在外面做空判断就非常灵活。
注意
如果是在ts
中,还需要对localStorage.getItem(key)
做一下null
的判断,因为ts
判断JSON.parse
只能接受字符串。
function getFromLocalStorage(key: string) {
const data = localStorage.getItem(key)
if (data === null) {
return null;
}
try {
return JSON.parse(data);
} catch (error) {
console.error(`Error parsing data from localStorage key "${key}": ${error}`);
return null;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。