如何調試 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