同学们好,我是 Eugene(尤金),一个拥有多年中后台开发经验的前端工程师~
(Eugene 发音很简单,/juːˈdʒiːn/,大家怎么顺口怎么叫就好)
你是否也有过:明明学过很多技术,一到关键时候却讲不出来、甚至写不出来?
你是否也曾怀疑自己,是不是太笨了,明明感觉会,却总差一口气?
就算想沉下心从头梳理,可工作那么忙,回家还要陪伴家人。
一天只有24小时,时间永远不够用,常常感到力不从心。
技术行业,本就是逆水行舟,不进则退。
如果你也有同样的困扰,别慌。
从现在开始,跟着我一起心态归零,利用碎片时间,来一次彻彻底底的基础扫盲。
这一次,我们一起慢慢来,扎扎实实变强。
不搞花里胡哨的理论堆砌,只分享看得懂、用得上的前端干货,
咱们一起稳步积累,真正摆脱“面向搜索引擎写代码”的尴尬。
引言
这是一段我看从别人的Axios代码里看到的代码片段
const msg = error.response?.data?.msg ?? error.response?.data?.message ?? error.message
起初这个?的用法,我只在定义接口的时候用过
export interface UserInfo {
id: string
pwd: string // 密码
nickname: string // 用户名称
wechatCode?: string // 微信号
}
表示:wechatCode是可选的,有也行没有也行。其他的都是一定要有的。
error.response?.data 我还能理解,表示error中是否有response,如果有就再.data如果没有就返回空嘛。但是??我就不能理解啦。怀揣着好奇心学习了一下,分享给同样不知道的同学们。
一、关键语法讲解
- 可选链操作符
?.作用:安全地访问嵌套对象的属性,如果访问路径上的某个属性是null或undefined,不会报错,而是直接返回undefined。
- 传统写法:如果直接写
error.response.data.msg,如果error.response是undefined,会抛出Cannot read properties of undefined (reading 'data')错误。 - 可选链写法:
error.response?.data?.msg会先检查error.response是否存在(非 null/undefined),存在才继续访问data,再检查data存在才访问msg,任何一步不存在就返回undefined。
2.空值合并操作符 ??
作用:只在左边的值是 null 或 undefined 时,才返回右边的值(区别于 ||,|| 会把 ''、0、false 等 “假值” 也判定为无效)。
- 例子:
undefined ?? '默认值'→返回 '默认值';'' ?? '默认值'→返回 ''(因为 '' 不是null/undefined)。
- 对比
||:'' || '默认值'→返回 '默认值',这是两者的核心区别。
二、整行代码分析
const msg = error.response?.data?.msg ?? error.response?.data?.message ?? error.message
这行代码的核心目的是:按优先级从 error 对象中提取错误提示信息,确保最终拿到一个有效的、非空的错误文本,查找优先级如下:
1、第一优先级:error.response?.data?.msg
先尝试从 error 的 response.data 里找 msg 属性(很多后端接口返回的错误信息字段是 msg)。
2、第二优先级:error.response?.data?.message
如果第一步的结果是 null/undefined(比如接口返回的错误字段是 message 而不是 msg),就尝试找 response.data 里的 message 属性。
3、最后兜底:error.message
如果前两步都没找到(比如没有 response 层级,比如前端自身抛出的错误),就取 error 本身的 message 属性(JS 原生 Error 对象默认有 message 字段)。
三、举例子讲解加深印象
const msg = error.response?.data?.msg ?? error.response?.data?.message ?? error.message
还是这个代码,用三种不同的接口情况返回让你更好的理解。下面的三个例子要和这条代码对照起来看。
假设有三种不同的 error 结构,看 msg 的取值结果:
例子 1:接口返回 msg 字段
const error = {
response: {
data: { msg: '用户名已存在' }
}
};
// 执行代码后,msg = '用户名已存在'(取第一优先级)
例子 2:接口返回 message 字段
const error = {
response: {
data: { message: '密码错误' }
}
};
// 第一步 msg 是 undefined → 第二步取 message → msg = '密码错误'
例子 3:前端原生错误(无 response 层级)
const error = new Error('网络请求超时');
// 前两步都是 undefined → 取 error.message → msg = '网络请求超时'
四、总结
?.是为了安全访问嵌套属性,避免因某个属性不存在导致代码报错;??是为了精准判断 “无值”(仅null/undefined),优先使用接口返回的错误信息,兜底用原生错误信息;- 整行代码的核心逻辑是:按
msg→message(接口层级)→message(错误对象层级)的优先级,提取有效的错误提示文本。
const msg = error.response?.data?.msg ?? error.response?.data?.message ?? error.message
通过本次学习,再结合案例分析一下。我发现这个写法似乎是前端处理异步请求(如 Axios)错误信息的常用最佳实践,能兼容不同格式的错误返回,保证代码的健壮性。
学习本就是一场持久战,不需要急着一口吃成胖子。哪怕今天你只记住了一点点,这都是实打实的进步。
后续我还会继续用这种大白话、讲实战方式,带大家扫盲更多前端基础。
关注我,不迷路,咱们把那些曾经模糊的知识点,一个个彻底搞清楚。
如果你觉得这篇内容对你有帮助,不妨点赞+收藏,下次写代码卡壳时,拿出来翻一翻,比搜引擎更靠谱。
我是 Eugene,你的电子学友,我们下一篇干货见~