如何调试 node_modules 源码?

前言

最近收到网友留言,在使用 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_modulessuperagent 库的 client.js 文件中的某个方法。

点击 client.js:468 跳转到对应的文件定义中。

468 行处打上断点,然后刷新页面,重新请求数据。

此时的 resbody 是有值的。

找到 res 的定义,打上断点,重新刷新浏览器,发现这个 resResponse 实例的返回值。

F11 或者直接点击进入方法图标,进入 Response 方法中。

最后在 Response 方法中找到 body 是根据 getResponseHeader() 方法中返回的 content-type 值是不是 application/json 来处理的。如果 responseHeader 中的 content-type 中包含 application/json,就将返回的 text 字符串进行格式化,然后保存在 body 中,前端代码中就直接使用 body 中解析好的 JSON 值了。

解决方法

通过上面的步骤,找到了问题出现的原因。但为什么 MockgetResponseHeader() 中获取的 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 linknpm link 的方式进行本地调试。

总结

调试 node_modules 包的小技巧为:

  • 通过 console.trace() 方法找到当前方法前面的调用栈。
  • 然后在浏览器的 Sources 中打上断点,然后一步步地去找排查原因。
  • 如果是 node_modules 中的包本身有问题需要调试,可以通过 yarn link 或者 npm link 的方式在本地进行调试。
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端