我只是做了這一堆的研究(見here,here,here和here)和回答你的問題是,節點不會讓你寫一個錯誤處理程序,將捕獲每個錯誤場景這可能會在您的系統中發生。
一些框架如express將允許你捕捉某些類型的錯誤(當一個異步方法返回一個錯誤對象時),但是還有其他一些你無法用全局錯誤處理器捕獲的條件。這是Node的限制(在我看來),並且可能與通常的異步編程有關。
例如,假設您有以下明確的處理程序:
app.get("/test", function(req, res, next) {
require("fs").readFile("/some/file", function(err, data) {
if(err)
next(err);
else
res.send("yay");
});
});
假設文件「一些/文件」實際上並不存在。在這種情況下,fs.readFile將返回一個錯誤作爲回調方法的第一個參數。如果你檢查並做下一步(錯誤)時,默認的錯誤處理程序將接管並做你做的任何事情(例如向用戶返回500)。這是處理錯誤的優雅方式。當然,如果你忘記打電話next(err)
,它不起作用。
所以這是錯誤狀況,全球處理器可以處理,但是考慮另一種情況:
app.get("/test", function(req, res, next) {
require("fs").readFile("/some/file", function(err, data) {
if(err)
next(err);
else {
nullObject.someMethod(); //throws a null reference exception
res.send("yay");
}
});
});
在這種情況下,還有如果你的代碼,導致你調用一個空的方法的錯誤目的。這裏會拋出異常,它不會被全局錯誤處理程序捕獲,並且您的節點應用程序將終止。所有當前在該服務上執行請求的客戶端都會突然斷開連接,而無法解釋爲什麼。不適度。
Node中目前沒有全局錯誤處理函數來處理這種情況。你不能在你的快遞處理程序周圍放置一個巨大的try/catch
,因爲當你的asyn回調執行的時候,那些try/catch
塊不再在範圍內。這只是異步代碼的本質,它打破了try/catch錯誤處理範例。
據我所知,你唯一的辦法在這裏是把try/catch
塊代碼的同步部位周圍的異步回調的每一個裏面,像這樣:
app.get("/test", function(req, res, next) {
require("fs").readFile("/some/file", function(err, data) {
if(err) {
next(err);
}
else {
try {
nullObject.someMethod(); //throws a null reference exception
res.send("yay");
}
catch(e) {
res.send(500);
}
}
});
});
那將會使一些討厭的代碼,特別是一旦你開始進入嵌套的異步調用。
有些人認爲,在這些情況下(即死亡),Node做的是正確的事情,因爲你的系統處於不一致的狀態,你沒有別的選擇。我不同意這種推理,但我不會就此進行哲學辯論。問題在於,使用Node時,您的選項很多很少,或者希望您的測試覆蓋率足夠好,以免發生這種情況。你可以在upstart或supervisor這樣的地方重新啓動你的應用程序,但這只是緩解問題,而不是解決方案。
Node.js有一個當前不穩定的功能,名爲domains,似乎解決了這個問題,但我對此不太瞭解。
這是_really_困擾我節點的一部分。我不能真的胃,但PHP至少有一個錯誤並不意味着_whole_網站關閉... – Merc 2017-11-23 15:08:39