这个项目是集成了第三方NeteaseCloudMusicApi项目的接口代码,我没有直接使用它的接口,因为需要再跑一个npm run开个端口,感觉很麻烦。
所以下定决心,使用拆分代码的方式,硬生生将这个api项目的部分api接口代码集成到了我自己的项目。当然前提是必须能看懂它的代码,然后才能做拆分,否则你根本无从下手
最后终于都搞定了,这个过程很复杂,把它的api代码拆分到了我自己的项目中。
但是有个问题,有时候请求歌曲的时候会报404错误
但是这个404错误报的明显不正确,因为我已经在代码里打了埋点:
上面证明:这个接口请求实际已经匹配到路由了,所以绝不应该是404错误!
然后排查代码发现这个第三方api的错误处理代码居然写的是404!
这就不对了,肯定起码应该是个500,但是这还不够,起码得知道是什么错误,
所以,把它的msg的值写成捕获到的err
本以为这样处理就应该能看到具体的异常信息了,但是实际返回结果却还是空对象:
问题变得棘手了,异常明明捕获到了啊,可是为什么打印不出来呢!
看来首先得看看这个err的原始信息是什么? 于是在catch代码块的开头先console.log一下这个err:
然后这个异常信息被打印出来了:
报错如下:
但是为什么把err赋值给msg就取不到值呢,然后断点调试看了一下这个error的数据结构:
然后结合GPT分析了一下,按理说: 通过err.message和err.stack应该可以获取到异常的具体信息:
然后确实看到了异常的具体信息了,这回没有报空值{}:
好了,小结一下:Javascript中Error对象必须通过message或者stack属性来获取到具体信息,
也就是err.message或者err.stack这种形式,不能把Error对象直接赋值给变量!!!否则变量获取的值就是空对象!
但是这种报错信息太难看了,应该根据报错指引,找到异常被触发的地方:
根据上面报错信息,找到song_url.js第33行:
这个地方说result没有sort属性,那么result本身极有可能也是个undefined!
所以非常有必要看看它的父级res到底是个什么东西
然后通过断点调试可以看到res底下果然没有data属性,那么result就必然是个undefined了,
难怪result.sort会触发Cannot read property 'sort' of undefined异常了
而且这里可以看到引发异常的真实原因:
所以在通过res.body.data获取result之前,要先判断一下res.body是否有data这个属性,
或者说判断res的返回状态是否正常,因为仅仅根据res.body是否有data属性来判断返回是否正常有点太片面了
然后,我找了一个请求成功的例子:
可以看到请求成功的时候:不仅res.body有data属性,res.body.code还等于200,
所以应该增加以下代码:在res请求失败的时候主动抛出异常,并将res.body作为异常信息:
但是在前面说的外部异常拦截的地方(catch err代码块),得到结果是:msg没能正确解构出异常的信息,显示的是: [object Object]
关于这个问题,我查了很久也查了很多资料,尝试了很多次,都没有能够解决问题。
可以说:这是这次问题排查中难度最大的地方
然后呢,我就尝试着从chatgpt对话,希望能找到答案。
最初按照它给的方法试了好几次,也还是不行。
最后我问了一个关键的神提问:
然后chatgpt终于给出了正确的回答:
这里的关键有两点:
1. 自定义异常信息时: new Error构造函数通常接收一个字符串作为错误信息的参数,而不是一个对象。
如果是接收参数是对象则必须通过JSON.stringify()方法转换成json字符串
2. 当已预知捕获的error是json字符串时,那么此时必须使用JSON.parse()方法把error.message转换成object对象,否则打印出来的就是[object Object]
所以,代码需要这样修改:
异常主动抛出的部分:
异常捕获的地方:
问题解决:前台msg信息终于正常显示出来了,不再是[object Object]
总结:
1. Javascript中的Error对象必须通过message或者stack属性来获取到它的具体信息,
也就是err.message或者err.stack这种形式。
不能把整个Error对象直接赋值给变量!!!否则变量获取的值就是空对象!
2. 自定义异常信息时: new Error构造函数通常接收一个字符串作为错误信息的参数,而不是一个对象。
如果是接收参数是对象则必须通过JSON.stringify()方法把该对象转换成json字符串
3. 当已预知捕获的error是json字符串时,那么此时必须使用JSON.parse()方法把error.message转换成object对象,否则打印出来的就是[object Object]