2016-07-14 17 views
3

我想在nodeJS中實現一個實用程序庫,我可以在不同的項目中使用它。我堅持如何正確處理錯誤。
例如,假設我有一個函數在nodeJS中拋出異常與錯誤對象

function dateCompare(date1,operator,date2) // it can take either a date object or valid date string. 

現在假設一個無效的輸入是提供─
1.我可以像異步邏輯電結果返回錯誤{錯誤:真,結果是:「」},但是這阻止我使用我的功能if((date1,'eq',date2) || (date3,'l3',date4)

2.如果我在此處拋出自定義異常,那麼恐怕節點是單線程的,創建錯誤上下文非常昂貴。

我們該如何處理它,使其易於使用以及不是很貴?

在什麼情況下,即使它太貴,拋出異常也會更合適?一些實際的用例將會非常有幫助。

回答

1

這樣的問題沒有「正確」的答案。有各種不同的哲學,你必須決定哪一個對你或你的上下文最有意義。

這裏是我的總體方案:

如果發現一個嚴重的編程錯誤,如需要的函數參數丟失或錯誤的類型,那麼我寧願只是拋出一個異常,並在異常拼出味精究竟是什麼錯誤。開發人員在第一次運行這段代碼時應該看到它們,並且應該知道它們需要立即修正它們的代碼。這裏的一般想法是,你希望開發人員立即看到他們的錯誤,拋出異常通常是最快的方法,你可以在異常中放入一條有用的消息。

如果有預期的錯誤返回值,例如「用戶名已被佔用」或「用戶名包含無效字符」,這些值不是編程錯誤,而僅表示給定操作(可能包含用戶數據)的原因不完整,那麼我會從傳遞這個信息給調用者的函數中創建返回值。

如果您的函數需要返回一個結果或一個錯誤,那麼您必須根據具體情況決定是否容易提出一系列容易檢測到的與成功不同的錯誤值返回值。例如,Array.prototype.indexOf()會返回負值以指示未找到該值或爲零,或者返回正數以指示其正在返回索引。這些範圍是完全獨立的,因此它們很容易編寫測試來區分它們。

引發異常的另一個原因是,您的代碼很可能會用於讓異常在多個調用級別或塊級別傳播而不是手動編寫代碼來傳播錯誤的情況。這是一把雙刃劍。雖然有時讓異常傳播非常有用,但有時您實際上需要了解並處理每個級別的異常,以便在錯誤情況下正確清理(釋放資源等),所以您不能讓無論如何,它會自動升高。

如果這樣的區別不是簡單的做你或者將要調用它的函數的代碼或者開發者,那麼有時返回一個具有多個屬性的對象是有意義的,其中一個屬性是錯誤屬性,另一個是值。

在你的具體情況:

function dateCompare(date1,operator,date2) 

if (dateCompare(date1,'eq',date2) || dateCompare(date3,'l3',date4)) 

這肯定將是方便,如果功能只是返回一個布爾值,並引發日期值或運營商的一個例外是無效的。這是否是一個好的設計決定取決於它將如何使用。如果你處於一個緊密的循環中,在很多值上運行這些值,其中很多值的格式不正確並且會引發這種異常,並且在這種情況下性能很重要,那麼返回上述對象可能會更好,改變你如何編寫調用代碼。但是,如果格式故障不是常規的預期情況,或者你只做了一次,或者異常與返回值的性能差異甚至不會被注意到(通常情況下),但是,如果格式故障不是常規預期情況,然後拋出異常 - 這是一種乾淨的方式來處理無效輸入,而不會污染函數的預期用例。

How can we handle it so that it is easy to use as well as not very expensive?

如果這種情況不是正常情況,那麼在異常輸入時拋出異常並不昂貴。此外,除非此代碼處於某種緊密循環並多次調用,否則您甚至不會注意到返回值與拋出/捕獲的異常之間的區別。因此,我建議您編寫代碼以使預期的情況更簡單,以便爲意外情況編寫代碼並使用異常。然後,您的預期代碼路徑不會進入異常路由。換句話說,例外實際上是正常的「例外」。

Under what circumstances throwing exceptions will be more appropriate even if it is too expensive?

請參閱上面的描述。

+0

感謝您的輸入。這很清楚。 – krrish