code-security.md
3.86 KB
代码健壮性
原则: 在接口数据返回失败或者错误的情况下,尽量保证页面正常打开,有问题的地方可以不显示内容。
数据校验
目前在我们的代码中最常见的两个异常是 - ReferenceError: a is not defined - TypeError: Cannot read property 'c' of undefined
处理原则
- 以function为单位,每个function确保自己内部的代码,数据安全访问
- 每个function不信任输入参数,在使用时都需要校验
- 2层以上的数据访问可以借助lodash的has或者get方法处理
- function 的私有变量都有默认值
例子
-
有问题的写法
const func = data => { let result = { name: 'name', size: data.opts.size, colors: [] }; let theData = data.data; let goods = theData.goods; goods.forEach(g => { if (g.opts && g.opts.colors) { let colors = g.opts.colors; let name = g.brandName.toLowerCase(); } }); };
-
推荐写法
const func = data => { let result = { name: 'name', size: _.get(data, 'opts.size'), //使用lodash, get colors: [] }; let theData = data.data || {}; //添加默认值 let goods = theData.goods; _.forEach(goods, g => { //使用lodash.forEach替代Array.prototype.forEach if (_.has(g, 'opts.color.name')) { // ... } let name = _.toLower(g.brandName); //一些js prototype的方法,可以使用lodash的工具方法替代 }); };
-
获取对象属性时,需判断对象是否定义
let func = data => { let a = data.data.a; let b = data.b; let c = data.list[0].name; b.c; // ... };
解决: 使用lodash get方法获取属性,赋值给局部变量时,需要给默认值
let func = data => { let a = _.get(data, 'data.a'); let b = data.b || {}; let c = data.list[0] || {}; b.c; c.name; // ... };
- 调用String.prototype、Array.prototype 的方法时,需要判断变量是否定义、或者类型是否正确
let s = data.s; s = s.toLowerCase(); // s 可能为定义 let list = data.list || []; list.forEach(console.log); // list不一定是数组
解决: 原生对象的一些方法,可以使用lodash的方法替代
s = _.toLower(s); _.forEach(data.list, console.log);
代码容错性
原则: 在接口数据返回失败或者错误的情况下,尽量保证页面正常打开,有问题的地方可以不显示内容。
Promise.all
在使用 Promise.all 并行请求多个接口时,如果其中一个失败,那么整个Promise.all都返回失败
在一些情况下,比如商品详情页请求了6-7个接口,其中有的数据没有访问,对页面并不会有太大影响,更不会影响整个购物流程,那么对失败的接口,我们给一个默认值
Since yoho-node-lib@0.0.48
const safePromise = global.yoho.safePromise;
let promises = [ promise1, promise2, promise3 ...];
Promise.all(safePromise(promises)).then(result => {
let data2 = result[1] || {}; // 当promise2接口调用失败, data2 默认为 undefined
if (!result[2]) { // 如果某一个接口的数据是必须的,可以自己判断抛出异常
throw new Error('some data must get');
}
});