提升代码健壮性
一、优化工作流程
设计文档评审
推动团队进行设计评审,于公可以写出更加健壮的代码,于私可以快速提升研发能力
Code Review
设计评审是保证代码质量的第一步,但设计文档和最终代码实现之间仍然可能会有很大的差异,只有对即将合入的代码进行严格的Code Review,才能发现哪些仅在特定条件下发生的异常
严格自测
交叉测试
自动化测试
二、不要相信用户
用户是非常不可控的因素,他们的性格、习惯、对互联网的熟悉程度、对产品的熟悉程度等等都差别巨大. 最好通过合理的规则进行约束
不要相信用户的输入
要做适当的格式校验或者转义
不要相信用户的权限
- 全量路由配置 + 拦截鉴权
- 每次鉴权实时调用用户最新权限。以性能换安全
- 前端校验,后端更新时,将用户token过期,前端重新登录。以体验换安全
const routes = [
//全量的路由配置
]
const router = new Router({
routes,
mode: 'history'
});
router.beforeEach(async (to, from, next) => {
//检查用户是否有将要跳转的路由权限
if (await checkPermission(to)) {
next();
} else {
//无权限处理,可以跳转到403页面
next('/403');
}
})- 动态路由
const router = createRouter({
history: createWebHistory(),
routes: [{ path: '/login', component: Login }],
})
//获取用户权限
//根据权限添加有权限的路由
router.addRoute({ path: '/vip', component: Vip })用户进入不存在的页面
- 错误的地址,需要让用户跳转到404页面,可以通过nginx配置或者路由配置进行设置
- 资源被删除,同上,或者根据需要单独配置
- 老地址,兼容老地址,并配置跳转到新路由
不应该的按钮点击
- 无权限按钮
指令封装
禁用不可点击按钮,如,未填写完的表单
防止重复点击,如,提交按钮,请求后给loading
三、"不相信"后端
考虑安全取值, res.data -> [] 但后端的默认值不一定是 []
四、不使用旧数据
表单同时编辑?
- 增加一个最后编辑字段 或 版本字段,后端校验是否一致
- 查询是否有人编辑
- 多人协同
五、不传递无用数据
PUT 类型,如修改 用户信息的 username
不应传整个 formData 这种情况可以合后端协商
六、错误捕获
JS 错误类型
- RangeError
RangeError 对象表示一个特定值不在所允许的范围或者集合中的错误。
在以下的情况中,可能会遇到这个问题:
a. 将不允许的字符串值传递给 String.prototype.normalize() b. 尝试使用 Array 构造函数创建一个具有不合法的长度的字符串 c. 传递错误值到数值计算方法(Number.toExponential()、Number.toFixed() 或 Number.toPrecision())。
- ReferenceError
ReferenceError(引用错误)对象代表当一个不存在(或尚未初始化)的变量被引用时发生的错误。
- SyntaxError
SyntaxError(语法错误)对象代表尝试解析不符合语法的代码的错误。当 Javascript 引擎解析代码时,遇到了不符合语法规范的标记(token)或标记顺序,则会抛出 SyntaxError。
- TypeError
TypeError(类型错误)对象通常(但并不只是)用来表示值的类型非预期类型时发生的错误。
以下情况会抛出 TypeError:
a. 传递给运算符的操作数或传递给函数的参数与预期的类型不兼容; b. 尝试修改无法更改的值; c. 尝试以不适当的方法使用一个值。
- URIError
URIError 对象用来表示以一种错误的方式使用全局 URI 处理函数而产生的错误。
- AggregateError
AggregateError 对象代表了包装了多个错误对象的单个错误对象。当一个操作需要报告多个错误时,例如 Promise.any(),当传递给它的所有承诺都被拒绝时,就会抛出该错误。
- InternalError
InternalError 对象表示出现在 JavaScript 引擎内部的错误。
通常描述某种数量过多的情况,例如:
"too many switch cases"(过多 case 子句);
"too many parentheses in regular expression"(正则表达式中括号过多);
"array initializer too large"(数组初始化器过大);
"too much recursion"(递归过深)。
EvalError
此异常不再会被 JavaScript 抛出,但是 EvalError 对象仍然存在,以保持兼容性。
监听错误发生
捕获页面资源加载情况
捕获Vue组件中的错误
Vue.config.errorHandler = function (err, vm, info) {
// handle error
// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子
// 只在 2.2.0+ 可用
}React组件ErrorBoundary
import { ErrorBoundary } from "react-error-boundary";
export function AddCommentContainer() {
return (
<ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
<AddCommentButton />
</ErrorBoundary>
);
}七、重视网络请求
后端接口再稳定,也挡不住用户网络异常等等原因,导致请求失败,因此要非常重视请求失败的处理。别忘记在请求失败后依然进行数据初始化。
async function init(){
try {
let res = await getUserList();
this.list = res.data || [];
} catch (e) {
//多考虑失败了如何处理
this.list = [];
}
}关注慢速网络
尽量不要请求全量数据
别忘记取消网络请求
八、不忘记清除定时器
组件已经销毁,但是定时器未清除,那么定时器中对组件数据和DOM的操作可能就会产生问题,或者因为大量的定时器未清除导致内存溢出等问题。
九、前端监控(可选)
总结
健壮性是衡量代码质量的一个重要指标。
代码的异常来源有很多,用户的操作、API接口、权限、网络、缓存、浏览器、操作系统、服务器、自身代码的缺陷等,都会导致前端产生异常。
