node.jsで例外処理をまとめようとしたら躓いた
したいこと
以下のようなコードがあったとする
const test = (a) => {
if (a == 1) {
try{
errorOcc("エラー出してほしい");
} catch(e) {
console.log("Error");
console.error(e);
}
} else {
try{
errorOcc("こっちもエラー出してほしい");
} catch(e) {
console.log("Error");
console.error(e);
}
}
}
こんなふうにtry-catchで多くの行数を占め、読みにくくなる。そこで、
const handleFunc = (method) => {
try {
method();
} catch (e) {
console.log("Error");
console.error(e);
}
}
こんな関数を作って、まとめたい。
まず、書いて動かしてみた(動かないコード)
まず動かないコードです、こんな感じで書けるのではと思いました。
const test = (a) => {
if (a == 1) {
handleFunc(errorOcc("エラー出してほしい"));
} else {
handleFunc(errorOcc("こっちもエラー出してほしい"));
}
}
その結果がこちら
Error: こっちもエラー出してほしい
at errorOcc (/home/akira/Documents/rtGraph/server.js:118:9)
at sessionCheck (/home/akira/Documents/rtGraph/server.js:128:18)
at /home/akira/Documents/rtGraph/server.js:89:7
at Layer.handle [as handle_request] (/home/akira/Documents/rtGraph/node_modules/express/lib/router/layer.js:95:5)
at next (/home/akira/Documents/rtGraph/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/akira/Documents/rtGraph/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/akira/Documents/rtGraph/node_modules/express/lib/router/layer.js:95:5)
at /home/akira/Documents/rtGraph/node_modules/express/lib/router/index.js:281:22
at param (/home/akira/Documents/rtGraph/node_modules/express/lib/router/index.js:360:14)
at param (/home/akira/Documents/rtGraph/node_modules/express/lib/router/index.js:371:14)
動いてそうなんですが、console.log("Error");
が呼ばれていないので、例外処理が通ってないんですね。関数呼び出されてるのに、例外処理が通らないってどういうことだよと思ったのですが、次のように書かないといけないそうです。
修正する(動いたコード)
const test = (a) => {
if (a == 1) {
handleFunc(() => {
errorOcc("エラー出してほしい");
});
} else {
handleFunc(() => {
errorOcc("こっちもエラー出してほしい");
});
}
}
これを動かすと以下のようになります。
Error
[2022-01-26T20:01:59.044] [ERROR] default - Error: こっちもエラー出してほしい
at errorOcc (/home/akira/Documents/rtGraph/server.js:118:9)
at /home/akira/Documents/rtGraph/server.js:130:7
at handlingFunc (/home/akira/Documents/rtGraph/server.js:110:5)
at sessionCheck (/home/akira/Documents/rtGraph/server.js:129:5)
at /home/akira/Documents/rtGraph/server.js:89:7
at Layer.handle [as handle_request] (/home/akira/Documents/rtGraph/node_modules/express/lib/router/layer.js:95:5)
at next (/home/akira/Documents/rtGraph/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/home/akira/Documents/rtGraph/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/home/akira/Documents/rtGraph/node_modules/express/lib/router/layer.js:95:5)
at /home/akira/Documents/rtGraph/node_modules/express/lib/router/index.js:281:22
npmのlog4jsを使っているので、要らないものも付いていますが、console.log("Error");
も呼び出され、無事、例外処理が行えていることが分かりました。
当初のコードでは動かなかった理由
記事を読んだ友人が、当初のコードでは動かない理由を教えてくれました。
const handleFunc = (method) => {
try {
method();
} catch (e) {
console.log("Error");
console.error(e);
}
}
const test = (a) => {
if (a == 1) {
handleFunc(errorOcc("errorOccを結果を代入している"));
} else {
handleFunc(() => {
errorOcc("これは関数自体を代入している")
});
}
}
test関数の中で呼び出している2つの例でhandleFunc(errorOcc("errorOccを結果を代入している"));
の方は、handleFunc
にerrorOcc("errorOccを結果を代入している")
の結果を代入しているので、handleFunc
の中で呼び出されているmethod()
では結果が表示されるのみなんですね。したがって、例外もここでは発生しないです。一方で、handleFunc
に無名関数を挟んでいる場合は、この無名関数自体を代入しているので、handleFunc
の中で呼び出されているmethod()
は関数になります。つまり、関数を代入したい場合は関数自体(関数オブジェクト)を代入しないといけないということだそうです。
参考
JavaScriptと非同期のエラー処理 / 中野 https://techblog.yahoo.co.jp/programming/javascript_error/ (2022-01-26閲覧)
Discussion