接口一异常你的前端页面就直接崩溃了?
前言
在 JavaScript 开发中,细节处理不当往往会导致意想不到的运行时错误,甚至让应用崩溃。可能你昨天上完线还没问题,第二天突然一大堆人艾特你,你就说你慌不慌。
来吧,咱们来捋一下怎么做才能让你的代码更健壮,即使后端数据出问题了咱前端也能稳得一批。
解构失败报错
不做任何处理直接将后端接口数据进行解构
const handleData = (data) => {
const { user } = data;
const { id, name } = user;
}
handleData({});
VM244:3 Uncaught TypeError: Cannot destructure property 'id' of 'user' as it is undefined.
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象(装箱)。由于 undefined
、null
无法转为对象,所以对它们进行解构赋值时就会报错。
第二种情况,虽然给了默认值,但是依然会报错
const handleData = (data) => {
const { user = {} } = data;
const { id, name } = user;
}
handleData({ user: null });
ES6 内部使用严格相等运算符(===
)判断一个变量是否有值。所以,如果一个对象的属性值不严格等于 undefined
,默认值是不会生效的。
Good 解法:
const handleData = (data) => {
const { user } = data;
const { id, name } = user || {};
}
handleData({ user: null });
数组方法调用报错
从接口拿回来的数据直接用当成数组来用
const handleData = (data) => {
const { userList } = data;
const newList = userList.map((item) => item.name);
}
handleData({ userList: null });
handleData({ userList: 123 });
VM394:3 Uncaught TypeError: userList.map is not a function
Good 解法:
const handleData = (data) => {
const { userList } = data;
if (Array.isArray(userList)) {
const newList = userList.map((item) => item.name);
}
}
handleData({ userList: 123 });
遍历对象数组报错
当数组中某项值是 null
或 undefined
const handleData = (data) => {
const { userList } = data;
const newList = userList.map((item) => item.name);
}
handleData({ userList: [null, undefined] });
VM547:3 Uncaught TypeError: Cannot read properties of null (reading 'name')
Good 解法:
const handleData = (data) => {
const { userList } = data;
const newList = userList.map((item) => item?.name);
}
handleData({ userList: [null] });
复杂情况的处理:
const handleData = (data) => {
const { userList } = data;
const newList = userList.map((item) => {
const { id, name, age } = item || {};
return `用户id是${id},用户名字是${name}, 用户年龄是${age}岁了`;
});
}
handleData({ userList: [null] });
当可选链操作符较多的情况时,无论是性能还是可读性,解构赋值会更好。
使用对象方法时报错
Object.entries 报错
const handleData = (data) => {
const { user } = data;
const newList = Object.entries(user);
}
handleData({ user: null });
VM601:3 Uncaught TypeError: Cannot convert undefined or null to object
Good 解法:
const handleData = (data) => {
const { user } = data;
const newList = Object.entries(user || {});
}
handleData({ user: null });
async/await 报错未捕获
常见错误:
const List = () => {
const [loading, setLoading] = useState(false);
const getData = async () => {
setLoading(true);
const res = await fetchListData();
setLoading(false);
}
}
Good 解法:
const List = () => {
const [loading, setLoading] = useState(false);
const getData = async () => {
setLoading(true);
try {
const res = await fetchListData();
setLoading(false);
} catch (error) {
setLoading(false);
}
}
}
JSON.parse 报错
JSON 字符串解析错误
const handleData = (data) => {
const { userStr } = data;
const user = JSON.parse(userStr);
}
handleData({ userStr: 'fdfsfsdd' });
16:06:57.521 VM857:1 Uncaught SyntaxError: Unexpected token 'd', "fdfsfsdd" is not valid JSON
Good 解法:
const handleData = (data) => {
const { userStr } = data;
try {
const user = JSON.parse(userStr);
} catch (error) {
console.error('不是一个有效的JSON字符串');
}
}
handleData({ userStr: 'fdfsfsdd' });
总结
以上列举了 JavaScript 在运行时可能会发生的错误,这些边界情况在开发时不那么容易察觉,静态检查工具如 ESLint 也无能为力。如果使用 TypeScript 可以帮助避免大部分问题,但即使不用 TS,也要在开发时考虑这些情况,才能写出更加健壮的代码。