前言
最近收到网友留言,在使用 Mock:Intercept and directly return data
插件时,接口成功被拦截,并且在 Console
中有打印。按照目前的逻辑,这是成功匹配到 Mock
接口的标识,但就是在代码中获取不到数据!
看到这里,我的第一感觉是会不会配置的数据结构与真实的接口返回不一致。比如需要返回的数据结构是:
css
{
"code": 0,
"message": "请求成功",
"data": {
"id": 1,
"name": "张三"
}
}
而实际返回的数据结构是:
json
"data": {
"id": 1,
"name": "张三"
}
会不会是少了一层包装?或者数据的类型不对?Number
类型的写成了 String
类型?
所以建议查看数据结构是否正确。
直到这两天参与到另外一个项目开发,该项目的接口请求使用的是 superagent
库。这个的场景和网友评论的几乎一样,Console
中有打印 Mock
成功的接口,可以是页面中就是不展示数据。
看到这里,又深刻地体会到了一个道理:出现问题,先从自己身上找原因
。
在这里,感谢提出问题的朋友!!!
好了,回到主题,之前的项目,使用 axios
一直没问题,为什么使用 superagent
就会出现这个问题呢?
查找原因
查看代码
scss
if (err || (result.body && !result.body.success)) {
// 异常报错
// ...
} else {
res(!!result.body && result.body.data);
}
发现项目中使用的是接口返回的 body
字段。打印 XMLHttpRequest
的返回值,对比正确以及不正确有什么不同。
正确的情况下,返回的 body
字段中是有值的。
错误的情况下,返回的 body
字段中没有值。
前后的不同找到了,现在就可以来找原因了。
查找 body 是在哪里被赋值的
刚才通过 console.log
的方式打印了返回值,但确不方便知道这个返回值中的 body
值是在哪里被赋值的。
通过 console.trace(result)
的方式进行打印。
console.trace()
不仅能打印出值,还能输出调用栈信息。
打印截图如下所示:
在右边可以看到在输出日志之前的一些调用栈。可以看到这里经历了 node_modules
中 superagent
库的 client.js
文件中的某个方法。
点击 client.js:468
跳转到对应的文件定义中。
在 468
行处打上断点,然后刷新页面,重新请求数据。
此时的 res
中 body
是有值的。
找到 res
的定义,打上断点,重新刷新浏览器,发现这个 res
是 Response
实例的返回值。
按 F11
或者直接点击进入方法图标,进入 Response
方法中。
最后在 Response
方法中找到 body
是根据 getResponseHeader()
方法中返回的 content-type
值是不是 application/json
来处理的。如果 responseHeader
中的 content-type
中包含 application/json
,就将返回的 text
字符串进行格式化,然后保存在 body
中,前端代码中就直接使用 body
中解析好的 JSON
值了。
解决方法
通过上面的步骤,找到了问题出现的原因。但为什么 Mock
的 getResponseHeader()
中获取的 content-type
为空呢?
正常情况下,接口返回时会指定 content-type: application/json;charset=UTF-8
。而 Mock
插件在拦截接口请求后,直接就返回了 responseText
。
所以这里,需要在 Mock
接口匹配成功后,再增加一下 getResponseHeader()
的返回值。
javascript
let getResponseHeader = ORIGIN_XHR.prototype.getResponseHeader;
NewXMLHttpRequest.prototype.getResponseHeader = function (headerName) {
const hasMockData = findMockResponse(this.requestURL, this.method);
// 如果 Mock 接口匹配成功,并且有请求 content-type 的值,就返回 application/json;charset=UTF-8 字符串
if (hasMockData && headerName && headerName.toLowerCase() === 'content-type') {
return 'application/json;charset=UTF-8';
} else {
getResponseHeader.apply(this, arguments);
}
};
经过以上修改,前面出现的问题就解决啦。
其它
本次的主要目的是找到 node_modules
包中出现问题的原因,node_modules
包并没有问题。
如果是要修改第三方包,还可以通过 yarn link
或 npm link
的方式进行本地调试。
总结
调试 node_modules
包的小技巧为:
- 通过
console.trace()
方法找到当前方法前面的调用栈。 - 然后在浏览器的
Sources
中打上断点,然后一步步地去找排查原因。 - 如果是
node_modules
中的包本身有问题需要调试,可以通过yarn link
或者npm link
的方式在本地进行调试。