2013-05-27 25 views
1

在官方的NodeJS文檔中有代碼示例,其中進程在域中存在異常時嘗試正常退出(它關閉連接,等待一段時間以等待其他請求,然後退出)。爲什麼NodeJS域的文檔代碼試圖終止這個過程?

但爲什麼不發送500錯誤並繼續工作?

在我的應用我想拋出一些預期錯誤(如FrontEndUserError),當用戶輸入是無效的,並在中間件某處捕獲這些異常送漂亮的錯誤消息客戶端。有了域名,它很容易實現,但是這有什麼缺陷嗎?

app.use (err, req, res, next) -> 
    if err instanceof FrontEndUserError 
    res.send {error: true, message: err.message} 
    else 
    log err.trace 
    res.send 500 

回答

0

讓我們看看你的web應用程序/服務器是一個狀態機。 。

除非你的應用程序是非常小的,這是非常不可能的,您知道每一個國家,你的機器都不可能在 當你得到一個錯誤,你有兩個選擇:

1)檢查錯誤並決定要做什麼,或者

2)忽略它。

在第一種情況下,您優雅地從一種狀態更改爲另一種狀態。在第二種情況下,你不知道你的機器處於什麼狀態,因爲你沒有看到錯誤是什麼。實質上,您的機器狀態現在是'未定義'。

正因爲如此,NodeJS建議如果錯誤一直傳播到事件循環,則會終止進程。再次,這個級別的赦免對於寵物項目和小應用來說可能是過度的,所以你的解決方案也很好。

但想象一下,如果你正在編寫一個銀行軟件,有一天你會得到一個你從未見過的錯誤,你的應用程序簡單地忽略它併發送一個500;但每次有人失去一個10萬美元。在這裏,我想要確保沒有錯誤到達事件循環,如果是,請使用詳細的堆棧跟蹤來終止進程以供日後分析。

+0

好的,但我可以在發送500(代碼示例更新)之前記錄跟蹤以供日後分析。所以,據我瞭解,唯一不好的是一些資源不會被釋放? –

+0

「如果錯誤一直傳播到事件循環,NodeJS建議終止進程」 - 請提供參考嗎? –

+0

「應對拋出的錯誤的最安全方法是關閉該過程。」在「警告:不要忽略錯誤!」下在域文檔中。 雖然domain和try/catch看起來可以做同樣的事情,但記住有關域的內容,您可以更好地控制哪些組件是域的一部分,以及能夠將特定操作綁定到與其父域不同的域。 –

1

domain模塊官方文檔:

截至如何作品在JavaScript中,幾乎從來沒有以任何方式安全地「拿起您離開的地方」的本質,沒有泄漏引用,或者創造一些其他的不明確的脆弱狀態。

最安全的方式,以響應拋出錯誤是關閉的過程...

對我來說,這意味着當事情在你的應用程序的NodeJS拋出一個錯誤,那麼你不幸做了。如果你確實關心你的應用程序的工作方式,結果對你很重要,那麼最好的辦法就是殺死進程並重新開始。然而,在最後幾毫秒內,你可以對其他客戶更好,讓他們完成工作,對新客戶說聲抱歉,如果你願意的話記錄幾件事情,然後殺掉進程並重新啓動它。

這就是NodeJS域模塊文檔示例中發生的情況。