天天看點

《寫給PHP開發者的Node.js學習指南》一1.2 堆棧追蹤

本節書摘來自異步社群《寫給php開發者的node.js學習指南》一書中的第1章,第1.1節,作者【美】daniel howard,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

寫給php開發者的node.js學習指南

在轉換過程中,會看到很多的堆棧資訊,非常之多。以下示例顯示了運作httpsvr.njs時,node-static npm包未安裝導緻的錯誤以及生成的堆棧資訊:

《寫給PHP開發者的Node.js學習指南》一1.2 堆棧追蹤

堆棧資訊的最上面一行顯示了抛出異常的代碼所在。這并不是産生錯誤的代碼,而是建立并抛出error對象的代碼。

這行之後,顯示的是error對象内部的錯誤資訊。這個錯誤資訊告訴了我們沒有找到node-static子產品。

其餘的部分稱為“調用棧”,是一系列由“at”開頭的鍊式函數調用,直到到達抛出異常的代碼。調用棧按照從内到外的順序排列。在本例中,function._resolvefilename()函數是調用棧的最頂端,表示它是最内層調用的函數,直接包含了抛出異常的代碼。._resolvefilename()函數被function._load()函數調用,該函數又被module.require()函數調用,module.require()又被require()函數函數,再上層就是object.()函數,依次類推。

在調用棧中每個函數的調用之後,你都會看到包含該函數的源檔案名,最後一行執行的代碼(可能是調用函數之前的一行或者抛出異常的那行),以及該行代碼中最後的執行位置。在上個例子中,可以看到涉及的兩個檔案是:module.js和httpsvr.njs。

module.js檔案存在于node指令中,我們并不認為這是屬于我們自己的代碼檔案,而httpsvr.njs則是我們自己的源代碼。盡管調用棧中隻顯示了一次httpsvr.njs,但是可以認為引起錯誤的是我們自己的代碼。一般來說,我們認為node.js本身,其内建的子產品,和其他安裝好的npm子產品都是安全可靠的。即使它們不是,我們也必須假定它們是正常工作的,除非我們證明排除了所有由我們的代碼産生錯誤的可能。但是,即使我們發現了錯誤是由其他原因導緻的,我們能控制的也隻有我們自己的源代碼。解決方式也應該是在我們的代碼中找到變通方案而不是通過漫長而緩慢的過程找到其他開發人員來修改他們的代碼。是以,結果是,不管最終的錯誤是什麼,首先需要關注的都是httpsvr.njs檔案。

我們需要關注的調用棧中的部分是:

《寫給PHP開發者的Node.js學習指南》一1.2 堆棧追蹤

函數調用在httpsvr.njs的第2行第14個位置。httpsvr.njs檔案為:

《寫給PHP開發者的Node.js學習指南》一1.2 堆棧追蹤

通過在源代碼中交叉引用調用,用于加載的node-static子產品的require()函數就是錯誤發生的地方。這和錯誤資訊“cannot find module ‘node-static’”一緻。

如果我們再看看調用棧,可以看到棧上方的function._load()函數和._resolvefilename()函數。看看這兩個函數名,我們可以猜測node.js環境加載該子產品出錯是因為找不到與子產品相關的檔案。是以可以做出假設找不到子產品檔案(可能是npm包)是因為子產品沒有安裝。再一次,這驗證了錯誤資訊“cannot find module ‘node-static’”。

object.函數暗示我們,require()函數的調用是在全局範圍内,而不是httpsvr.njs使用者自定義範圍。但是事實并不一定都是這樣。一個匿名對象也有可能在使用者自定義的函數内生成。但是,繼續看調用棧,在object.函數調用之後,我們看到調用者是module.js中的module._compile函數。是以,require()函數是全局範圍内的調用。

綜合以上所有資訊,一個解決方案是安裝node-static npm package:

《寫給PHP開發者的Node.js學習指南》一1.2 堆棧追蹤

誠然,不需要每次在看node.js調用棧時都做這些分析。但是你可能會看到很多很多的調用棧,你應該知道如何進行分析——特别是因為找到并修複錯誤占據了轉換過程95%的時間。

總結一下,分析一個調用棧資訊的過程是:找到錯誤,檢視錯誤資訊(如果有的話),做出假設并關注在自己代碼中的特定函數調用,閱讀代碼并找出錯誤可能産生的位置,檢視調用棧是否包含更多錯誤的可能資訊,根據堆棧資訊了解伺服器如何執行到該調用函數。

上一篇: Arrays.asList