実現したいこと
JavaScript で await
を忘れたときに catch
したいです。
発生している問題
該当のソースコードについて、[実行➁] の場合に値が確認できなくて困りました。
[実行➀] await
あり
-> ブラウザ開発ツールで {args: 'illegal'}
が確認できる
[実行➁] await
を忘れた
-> ブラウザ開発ツールで {args: 'illegal'}
が確認できない
具体的に言いますと、[実行➁] において unhandledrejection
が反応せず、await
を忘れたときにブラウザ開発ツールで制御できないという問題です。
await
を忘れたときも、{args: 'illegal'}
を確認したいのですが、良い方法はありますか?
該当のソースコード
ポイントとしては、handle-unhandled-errors.js ファイルのwindow.onerror
と unhandledrejection
で制御しているつもりなのに、await
を忘れたときにどちらも反応してくれない!という点です。
main.js
JavaScript
1import { initApp } from "./init-app.js"; 2import { handleError } from "./handle-error.js"; 3 4(async () => { 5 try { 6 // [実行➀] await あり 7 // -> 問題なく開発ツールで {args: 'illegal'} が確認できる 8 // await initApp(); 9 10 // [実行➁] await を忘れた 11 // -> 確認できない 12 initApp(); 13 } catch (error) { 14 handleError(error); 15 } 16})();
init-app.js
JavaScript
1import { hoge } from "./hoge.js"; 2 3export const initApp = async () => { 4 await hoge(); 5};
hoge.js
JavaScript
1import { fuga } from "./fuga.js"; 2 3export const hoge = async () => { 4 await fuga(); 5};
fuga.js
JavaScript
1import { validate } from "./validator.js"; 2 3export const fuga = async () => { 4 const args = "illegal"; // 不正な値で検証時に throw する 5 validate(args); 6};
validator.js
JavaScript
1import { CustomError } from "./CustomError.js"; 2 3export const validate = (args) => { 4 if (args === "illegal") { 5 throw new CustomError("不正な値です.", { args }); 6 } 7 8 return true; 9};
handle-error.js
JavaScript
1export const handleError = (error, options = {}) => { 2 error.logError(options); 3};
CustomError.js
JavaScript
1// 第二引数に確認用の debugInfo を持ったエラー 2export class CustomError extends Error { 3 constructor(message, debugInfo = {}) { 4 super(message); 5 this.name = "CustomError"; 6 this.debugInfo = debugInfo; 7 } 8 9 logError() { 10 if (this.hasOwnProperty("debugInfo")) { 11 console.error(this.stack, this.debugInfo); 12 } else { 13 console.error(this.stack); 14 } 15 } 16}
handle-unhandled-errors.js
JavaScript
1import { CustomError } from "./CustomError.js"; 2 3window.onerror = function (message, source, lineno, colno, error) { 4 console.log("未制御例外を処理します", { error }); 5 6 if (error instanceof CustomError) { 7 if (error.hasOwnProperty("debugInfo")) { 8 console.error("Unhandled", error.stack, error.debugInfo); 9 } else { 10 console.error("Unhandled", error.stack); 11 } 12 13 // true を返し, throw によるデフォルトのコンソール出力を防ぐ 14 return true; 15 } else { 16 // どうせ window.onerror までしかスタックを追えぬので 17 // ここはデフォルトのコンソール出力を使う 18 return false; 19 } 20}; 21 22// async など Promise の過程は onerror が使えないので addEventListener する 23window.addEventListener("unhandledrejection", (event) => { 24 const error = event.reason; 25 26 console.log("Promise系の未制御例外を処理します", { error }); 27 28 // 文字列や非Errorオブジェクトもカバーする 29 const isErrorInstance = error instanceof Error; 30 const message = isErrorInstance 31 ? error.message 32 : typeof error === "string" 33 ? error 34 : JSON.stringify(error); 35 36 const stack = 37 isErrorInstance && error.stack 38 ? error.stack 39 : "No stack trace available"; 40 41 const debugInfo = 42 isErrorInstance && "debugInfo" in error ? error.debugInfo : null; 43 44 if (debugInfo) { 45 // デフォルトのエラーハンドリングを防ぎ, 代わりに debugInfo つきの console.error を実行 46 event.preventDefault(); 47 console.error("Unhandled", stack, debugInfo); 48 } else { 49 // デフォルトのエラーハンドリングが一番情報が多いのでここは何もしない 50 } 51 52 // logErrorToServer({ 53 // message, 54 // stack, 55 // }); 56});
試したこと
下記 [実行➂] のように、initApp()
の返り値を確認し、await
を忘れた場合にも catch
で拾うように Promise.catch
を明示してみました。
main.js (修正バージョン)
JavaScript
1import { initApp } from "./init-app.js"; 2import { handleError } from "./handle-error.js"; 3 4(async () => { 5 try { 6 // [実行➀] await あり 7 // -> 問題なく開発ツールで {args: 'illegal'} が確認できる 8 // await initApp(); 9 10 // [実行➁] await を忘れた 11 // -> 確認できない 12 // initApp(); 13 14 // [実行➂] await を忘れた場合にも catch で拾うように Promise.catch を明示 15 // -> 確認できたけどこれ書くならそもそも await を書き忘れることはない 16 const result = initApp(); 17 if (result instanceof Promise) { 18 result.catch((error) => handleError(error)); 19 } 20 } catch (error) { 21 handleError(error); 22 } 23})();
すると確認できましたが、これを書くならそもそも await
を書き忘れることはないでしょうからダメダメな気がいたします・・
理想としては handle-unhandled-errors.js の修正による解決で、「await
を書き忘れてもいつだって僕がなんとかしてあげるよ!」みたいな頼れる感じのやつなのですが、良い方法ございますでしょうか?
補足情報(FW/ツールのバージョンなど)
Google Chrome 利用ですが、利用ブラウザに関わらず確認できるようにしたいなと思っています。
以上です。
よろしくお願い致します。

回答3件
あなたの回答
tips
プレビュー