在和后端打交道时,前端同学必须遵循一个原则:不要相信后端。这里不是说你们的基友关系,私下可以是好朋友,但是一定不要信任他们返回来的数据格式。
有经验的前端同学都知道,不是所有后端都会严格按照API来返回数据的,特别是空值的情况,比如本来我们期望后端返回一个空数组,结果他们返回一个null,本来我们期望返回一个字符串,结果他们啥都没有返回,如果前端不加兼容,代码就很容易崩溃。
let res = { data: { items: null //预期是数组,结果返回了null } } //下面这段代码直接崩溃了 res.data.items.forEach(item =>{ }) //这里也崩溃了 let tags = res.data.tags.split(',');
上面这个示例,我们内心其实认定了 res.data.items一定存在,且是Array类型,而res.data.tags一定存在且是String类型,不过可惜后端返回的格式并不对,而如果要写出非常兼容的代码也很麻烦。
import _ from 'lodash'; let res = { data: { items: null } } //尝试写出兼容的代码 (_.get(res, 'data.items') || []).forEach(item =>{ })
一般情况下我都是像上面这么处理的,通过lodash.get方法安全取值,然后如果没有值时就给它赋予一个空数组,不过这仍然有风险,万一 _.get(res, 'data.items') 是对象格式岂不又崩溃了,所以这样写还不够安全,但是如果各种情况都考虑,代码就太复杂了。
import _ from 'lodash'; let res = { data: { items: null } } //尝试写出兼容的代码 let items = _.get(res, 'data.items'); if(!Array.isArray(items)){ items = [] } items.forEach(item =>{ })
这太复杂了,要是到处都写这样的代码那就烦死了,也很不优雅,能不能封装一个方法,既能安全取值,又保证返回的数据格式一定是我们想要的。基于这个思路就想着扩展几个lodash的方法,lodash支持通过 mixin扩展方法。扩展以下2个方法:
promiseArray(obj, path): 从obj的path中安全取值,并确保返回的一定是Array格式
promiseString(obj, path): 从obj的path中安全取值 ,并确保返回的一定是String格式
import _ from 'lodash'; //扩展lodash方法 _.mixin({ promiseArray: function (obj, path){ let value = _.get(obj, path); return Array.isArray(value) ? value : [] }, promiseString: function (obj, path){ let value = _.get(obj, path); return typeof value === 'string' ? value : '' }, }) let res = { data: { items: null } } //业务代码中这么使用 //放心大胆地调用数组方法吧 _.promiseArray(res, 'data,items').forEach(item =>{ }) let tags = _.promiseString(res, 'data.tags').split(',');
怎么样,是不是特别的优雅,而且也仅仅只是简简单单的封装了一下,毫无技术含量,相信大家都可以自行实现。好了,有没有人能封装下 promiseObject方法~~