如何調試 node_modules 源碼?
前言
最近收到網友留言,在使用 Mock:Intercept and directly return data 插件時,接口成功被攔截,並且在 Console 中有打印。按照目前的邏輯,這是成功匹配到 Mock 接口的標識,但就是在代碼中獲取不到數據!
看到這裏,我的第一感覺是會不會配置的數據結構與真實的接口返回不一致。比如需要返回的數據結構是:
{
"code": 0,
"message": "請求成功",
"data": {
"id": 1,
"name": "張三"
}
}
而實際返回的數據結構是:
"data": {
"id": 1,
"name": "張三"
}
會不會是少了一層包裝?或者數據的類型不對?Number 類型的寫成了 String 類型?
所以建議查看數據結構是否正確。
直到這兩天參與到另外一個項目開發,該項目的接口請求使用的是 superagent 庫。這個的場景和網友評論的幾乎一樣,Console 中有打印 Mock 成功的接口,可以是頁面中就是不展示數據。
看到這裏,又深刻地體會到了一個道理:出現問題,先從自己身上找原因。
在這裏,感謝提出問題的朋友!!!
好了,回到主題,之前的項目,使用 axios 一直沒問題,爲什麼使用 superagent 就會出現這個問題呢?
查找原因
查看代碼
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() 的返回值。
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的方式在本地進行調試。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/IKSgtB2JtYX602JdiVag2g