2013-11-26 59 views
6

我在寫一個與REST API交談的模塊,由於REST API提供了很好的語義錯誤響應(例如403與503),我想將這些語義錯誤傳達給調用者。在Node.js中公開和編寫錯誤的最佳方式是什麼?

(編輯:我的意思是,調用者應該能夠以編程方式理解錯誤的原因,並採取相應的行動,如顯示相應的UI)

什麼是我做的最好辦法所以?

  1. 爲這些語義創建我自己的Error子類,例如, mymodule.ForbiddenErrormymodule.ServiceUnavailableError?呼叫者然後將檢查instanceof來派生語義。這在靜態類型語言(如C#和Java)中最爲典型。

  2. 添加例如mymoduleCode屬性到標準Error實例,其語義字符串如'Forbidden''ServiceUnavailable'。 Node.js本身就是這樣做的,例如code: 'ECONNREFUSED'

  3. 還有其他的一些方法嗎?

==

現在我正在寫另一個模塊,封裝了第一個模塊。我不想直接暴露內部模塊的錯誤,但爲了可調試性,編寫/包裝它們會很好。

對我來說,最好的辦法是什麼?

  1. 添加例如,一個internalError屬性給我的Error實例,該實例引用了內部模塊的Error實例。 C#和Java再次做到這一點。 (Exception#InnerException/Throwable#cause

  2. 還有其他的方法嗎?

我見過的大多數工具,不過,只顯示Error實例stack屬性,因此這個數據會迷失在這種情況下。有沒有一種典型的/傳統的方式已經存在?

回答

4

發現這一點,談到這篇大文章:

http://www.joyent.com/developers/node/design/errors

太給粘貼在這裏,但在 「具體建議」,項目2至5個地址是:

  1. 清楚你的功能在做什麼。
  2. 使用Error所有錯誤的對象(或子類),並執行Error合同。
  3. 使用錯誤的name屬性以編程方式區分錯誤。
  4. 增廣Error對象與解釋細節
  5. 屬性如果你通過一個低級別的錯誤,以您的來電者,應考慮包裝它來代替。

,特別是,文章鏈接到本模塊包裝/合成錯誤:

https://github.com/davepacheco/node-verror

我不知道我會需要遵循以下確切約定 - 例如我看到有價值的應用領域code財產 - 但原則是非常有幫助的。

+0

node-verror很好,但有一個問題是致命的IMO - 嘗試打印空值/未定義字符串時崩潰。你可以試試這個解決這個問題的分支:https://github.com/naddison36/node-verror – Michael

+0

有沒有人知道這裏的「推動錯誤契約」在#2中是什麼意思? – fraxture

+0

我假設它是指設置'name','message'和'stack'(通過'Error.captureStackTrace')。 –

1

編輯我是StackOverflow的新手 Node.js.其他人應該回答這個問題! :-)

如果您來自Java/C#歡迎使用JavaScript!我從來沒有見過Node.js庫使用instanceof來檢查錯誤類型,但正如你所說的,在靜態語言中很常見。

就是這樣,通常只是創建新的錯誤,並回調那些使用NodeJS的回調風格(err, response)

我一直會遇到來自其他模塊的錯誤消息,並且知道它們來自哪裏與創建包裝的錯誤消息可能會有幫助,這些錯誤消息可能會隱藏它實際上死在我身上的地方(需要更多的東西來挖掘) 。

創建一個可以處理那些字符串其餘的錯誤消息的函數(或在您的情況下,無效的響應)的例子:

function myFunction(callback) { 
    callRestAPI('http://someApi.com/request', function(errorString, jsonResponse) { 
     if (errorString) { 
      callback(new Error("something wrong in myFunction! " + errorString)); 
     } else { 
      callback(null, JSON.parse(jsonResponse)); 
     } 
    }); 
} 

在你的情況下,「Errorstring,則」檢查將主要是響應( 403/503),並且您可以將錯誤消息的結構發送到new Error(...),例如new Error('Failed! Got response 403!')

我可能已經錯過了你的觀點,也許別人能更徹底。


重新閱讀後,你可以發佈你打包的模塊。它是節點請求嗎?

+0

嘿格雷羅,謝謝你的回覆!我對Node並不陌生,但我很欣賞這種歡迎。 =)我可以在我的問題上更清楚:當我說「語義」時,我的意思是暴露一個事實,例如這是一個客戶端權限錯誤與服務器過載錯誤;所以它不應該在字符串消息中。節點核心爲其錯誤添加一個「代碼」屬性;這可以讓調用者區分錯誤原因/類型。但是這並不適合太好的組合。那有意義嗎? –

+0

我一直在問這個問題,但我正在尋找的一個具體案例是我維護的這個數據庫驅動模塊:http://npmjs.org/package/neo4j然後我將它包裝在一個業務邏輯模塊我正在寫一個應用程序。目前,這個db模塊只是拋出非語義標準的'錯誤'實例w /字符串消息;我想改變這一點。 –

+0

我可能是最糟糕的人回答這個。我對Node.JS非常陌生。祝你好運:D –

1

我很新的節點一樣,所以藉此與一粒鹽,但我會用你的#2選項去,增加的屬性。 (This is also suggested here)

這是非常原始的#2選項。如果錯誤處理程序只記錄堆棧,而不是錯誤本身,那是他們的錯。 :-)(嚴重的是,不知道你如何能做到更好)

+0

感謝您的鏈接!你如何認爲你會編寫錯誤呢?只需使用你自己的屬性(y/ies)來擴展原始實例? –

+1

是的。我會添加一個屬性,命名爲'semanticDetails'或'aseemSays'。 :-)它可能是一個字符串,或者它可能是一個具有多個屬性的本身:'.moduleName','.errorCode'等等......將它記錄下來,以便接收錯誤的程序員知道在哪裏尋找。 – user949300

6

您所描述的用例是一個絕對的節點現在水平低下。由於存在慣例,因此它們往往是以下幾種混合:

  1. 創建從Error構造函數中派生的新的錯誤類型。主要用於創建高級錯誤類別。你可以使用instanceof來區分錯誤的類型,但這並不感覺非常好。
  2. 創建將另一個錯誤作爲構造函數參數並將其包裝的Java樣式的錯誤子類型。如果你讓這個子類型暴露一個API,你基本上是使用多態而不是直接調度來處理基於類型的錯誤。
  3. 通過Error構造函數創建語義有用的錯誤消息。這是我傾向於使用很多的模式。
  4. 將屬性附加到錯誤,這也非常常見。
  5. 創建一個分離的錯誤處理API,可以從錯誤發生的任何地方調用。這爲您提供了一個集中所有代碼的單獨地方,這些代碼可以指出您有哪些錯誤以及應該如何處理它,並注入處理錯誤所需的任何依賴關係。

這裏真正的問題是這些都是特設機制,我不會說他們中的任何一個都達到了臨界質量。我認爲這部分歸因於異步性和JavaScript的組合使得正確和完全處理錯誤變得困難,所以建議通常在捕獲有關錯誤的信息後關閉整個過程。

這並不做處理預期的錯誤了偉大的工作,但我想大多數這些錯誤要麼由框架(例如快遞的錯誤處理)抓獲或被置於節點回調約定。總之,我認爲這裏有空間來定義一些約定,因爲藝術的狀態並不那麼巧妙。

+0

感謝您的不錯總結。我可否建議加入'aseemSays'物業作爲標準? :-) – user949300

+0

感謝Forrest,同意很好的總結。你是對的,大多數時候錯誤不是/不需要在語義上進行分析,但我遇到過幾種情況。例如。我調用一個函數來註冊一個新用戶,並且它會拋出一個錯誤。那個BC是數據庫關閉了嗎?或bc「獨特的電子郵件」約束失敗?我想在這兩種情況下采取不同的行動。聽起來像附加屬性是你在那裏做什麼? –

0

我只是附加一個httpCode屬性錯誤對象。KISS

+0

這在我的例子中聽起來很合理,但在這種情況下,假設REST API是一個實現細節。例如。如果您使用模塊與服務X交談,則不需要知道X的REST API的詳細信息,例如其各種狀態代碼。 –

相關問題