后端返回null,前端怎么处理?数据容错——不用过分相信外部数据

场景

我们在开发过程当中,总是会遇到因为数据原因,导致使用数组方法或者获取对象属性的时候报错。

xxx is not fuction

Cannot read property xxxx of undefined

因为这些错误,会导致直接页面打不开,所以我们一般会做一些容错处理,从而让页面可以正常打开。例如:&& 、三元运算符,甚至有时会看到 if 语句来处理。

常见方式

 1 // response 是来自接口的数据
 2 const response = { 
 3     code: 200, 
 4     msg: 'message', 
 5     data: { 
 6         total: 100, 
 7         page: 1, 
 8         pageSize: 10, 
 9         content: [] 
10     }
11 }
12 
13 const goodsList = response.data.content.forEach(() => {})
14 const total = response.data.total

 

为了保证取data、content属性和使用forEach不报错,可能会这样做

1 const goodsList = response.data && response.data.content && response.data.content.forEach(() => {})
2 const total =  response.data && response.data.total

 

这样就初步完成了数据容错,但是代码过于冗余可读性差,而且 total 的值还会可能变成 Boolean 类型。

简单改进

只需要简单的两个处理,一个是解构,一个是给默认值

1 const { data = {} } = response
2 const { constent = [], total = [] } = data
3 goodsList.forEach(() => {})

 

解构是非常有必要的,增加代码可读性和扁平化数据

不过,但这里又有了新的问题。这个时候如果我得到数据如下的样子:

1 const response = {
2     data: null
3 }

 

那么解构就会报错 Cannot destructure property content of 'undefined' or 'null'

默认值生效的条件是,对象的属性值严格等于undefined

上面代码中,属性data等于null,因为null与undefined不严格相等,所以是个有效的赋值,导致默认值 {} 不会生效。实际就成了如下的样子:

1 const { constent = [], total = [] } = null 

 

因此我们得保证拿到的数据不能存在null,不然上面的代码就没意义了。

进一步改进

你可能在想和后端约定好不返回 null 就好了

但是不能过分相信外部数据,包括约定之后的

这种情况其实可以在封装axios 或者fetch的时候,在里面添加一个过滤的函数,把从接口拿到的数据过滤一下,过滤掉值为 null 的数据,或者是把为 null 的数据重新赋值为 undefined。

下面是过滤数据的函数

 1 // 把获取到的数据过滤一遍
 2 const replaceNull = (obj) => {
 3     for (let key in obj) {
 4         switch (Object.prototype.toString.call(obj[key]).slice(8, -1)) {
 5             case 'Object': 
 6                 replaceNull(obj[key])
 7                 break;
 8             case 'Array': 
 9                 for (let i = 0; i < obj[key].length; i++){
10                     replaceNull(obj[key][i])
11                 }
12                 break;
13             default:
14                 if (obj[key] === null) obj[key] = undefined;
15         }
16     }
17 }

 

过滤之后,这个时候这种写法就没问题了

1 const { data = {} } = response
2 const { constent = [], total = [] } = data
3 goodsList.forEach(() => {})

 

当然如果你们有node作为中间层,前端视图层是可以放心的使用解构默认值的,比如 graphQl 这种。

结束语

前端数据容错处理是必须的,不能期待外部数据的格式就是自己想要的。不知道大家平时都是怎么处理的。

posted @ 2019-12-05 12:35  蒋大忙  阅读(4946)  评论(0编辑  收藏  举报