前端程序员的错误处理和防御式编程

159 阅读3分钟

编程要小心谨慎,如履薄冰。此篇简单总结一下前端常用的如何防止出错的方法。

1. 避免访问null或者undefined的成员变量 大部分的错误和这个有关系

//1. 使用 ?  
map[prize.rewardType]?.text

navigator?.connection?.type

//2. 使用 || 
function getObj(){
	return null
}
let {value=null}=getObj() || {}
let {value=null}=(await getPromise())||{}

//3. 检测对象是否存在 不推荐
if(getObj){
	
}

2.一些可能会出错的操作添加try-catch防御一下 例如json解析

function parseRule(rule) {
    try {
        return JSON.parse(rule)
    } catch (error) {
        return null
    }
}

总结一下特别容易的场景:

1. json解析
2. 字符串match方法,如果匹配不到,返回的是null,匹配得到,返回的是数组
	const text = "John Doe, Jane Doe";
	const pattern1 = /John/;
	console.log(text.match(pattern1)); // ["John"]
3. 解构null或者undefined

3.接口请求的处理

需要注意的一点是,接口请求总是有2种情况,成功或者失败,所以两条分支都要处理。
不成熟的程序员往往只会处理成功的分支,但我们成熟的程序员就永远都要考虑两种情况。

推荐使用Promise的then和catch来处理,当然也可以使用try-catch。


一般我们的接口会进行统一管理,例如
//user.js
export function fetchUserListInfo(){
    return request({
        url:'/user/info'
    }).then(res=>{
        // 这里也可以对响应的数据进行处理,例如 return res.data.map(item=>handleUserInfo(item)) 
        //如果处理过程报错了,也会被下面catch到 
        return res.data
    }).catch(err=>{
        // 处理err,也可以不处理,因为err一般都在接口拦截那里统一处理
        return null
    })
}

//组件中的代码
const users=await fetchUserListInfo()
// users为null,说明出错了
if(!users)return 
// 如果users不为null,说明没毛病


这样处理接口有一些好处
1. 即我们可以很方便地进行测试,假如接口还没准备好,我们就可以自己先返回一些数据先用着
export function fetchUserListInfo() {
    // 接口没有准备好,可以自己先返回一些测试数据
    return Promise.resolve({
        errCode: 0,
        data: [
            { id: 0, name: 'Peter', age: 18 },
            { id: 1, name: 'Ross', age: 32 }
        ]
    })
    // 原来的代码先注释掉
    //     return request({
    //         url:'/user/info'
    //     }).then(res=>{
    //         // 这里也可以对响应的数据进行处理,例如 return res.data.map(item=>handleUserInfo(item))
    //         //如果处理过程报错了,也会被下面catch到
    //         return res.data
    //     }).catch(err=>{
    //         // 处理err,也可以不处理,因为err一般都在接口拦截那里统一处理
    //         return null
    //     })
}
2. 可以很方便测试出错的流程,不成熟的程序员只会测试成功的流程,失败的分支很少走到,但我们成熟的程序员每条分支都要测试到。

export function fetchUserListInfo() {
    // 测试失败的流程
    return Promise.resolve(null)
    // 原来的代码先注释掉
    //     return request({
    //         url:'/user/info'
    //     }).then(res=>{
    //         // 这里也可以对响应的数据进行处理,例如 return res.data.map(item=>handleUserInfo(item))
    //         //如果处理过程报错了,也会被下面catch到
    //         return res.data
    //     }).catch(err=>{
    //         // 处理err,也可以不处理,因为err一般都在接口拦截那里统一处理
    //         return null
    //     })
}


4. vue和react等框架要关注状态的流转

vue、react等现在框架的视图都是根据状态渲染的,如果视图渲染有问题,大部分是状态的问题,所以我们要关注状态的流转。

关注状态的生命周期 
初始化时的状态 
修改之后的状态 
结束之后的状态

越是复杂的项目越需要这样,写代码之前最好把状态的流转搞的清清楚楚,这样就很少会出错。

先写这些,想到了再补充,欢迎评论、指正。