Promise のエラーを常に見つけることの重要性
P粉590929392
P粉590929392 2024-03-19 21:05:20
0
1
436

私はプロジェクトで @typescript-eslint/no-floating-promises ルールを使用します。このようなコードを書くと、このルールは文句を言います -

functionReturningPromise()
    .then(retVal => doSomething(retVal));

この Promisecatch ブロックを追加する必要があります。例外処理ブロックにロジックを追加したい場合、これは理にかなっています。しかし、それが必要ない状況もたくさんあります。エラーがスローされたことに満足しています。したがって、このルールによってスローされるエラーを抑制するために、私はこれを行うことになりました -

functionReturningPromise()
    .then((retVal) => doSomething(retVal))
    .catch((エラー) => {
        エラーをスローします。
    });
上記のように catch ブロックを追加しなくても、error は同じようにスローされます (少なくともコンソール出力には表示されます)。したがって、この catch ブロックを明示的に指定する意味がわかりません。私は何か見落としてますか? catch ブロックを追加する場合と追加しない場合で、error がスローされる方法に実際の違いはありますか?

P粉590929392
P粉590929392

全員に返信(1)
P粉106711425

コメント投稿者は皆、あなたの質問にうまく答えていますが、これがなぜ重要なのかを例で説明するには、次のコードを想像してください:

Promise.reject();
setTimeout(() => console.log('hello'), 1000);

このコードはかなり無害に見えます。未処理の no-op 約束拒否があり、プログラムは起動後 1 秒後に 'hello' をログに記録します。

ブラウザでは、まさにこれが起こります。ブラウザは「Uncaught Promise Rejection」エラーをログに記録しますが、それ以外の場合は無視します。

ただし、NodeJS (Node v15 以降) では、未処理の Promise 拒否は ハード エラーです。 つまり、エラーが検出されるとプロセスが終了します。

これは、ターミナルでコードを実行することで確認できます (-e は「このコード文字列を評価して実行する」という意味です)

$ ノード -e "Promise.reject(); setTimeout(() => console.log('hello'), 1000)"
ノード:内部/プロセス/約束:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

[UnhandledPromiseRejection: このエラーは、catch ブロックなしで非同期関数内でスローしたか、.catch() で処理されなかった Promise を拒否したことによって発生しました。Promise は、「未定義」という理由で拒否されました。] {
  コード: 'ERR_UNHANDLED_REJECTION'
}

Node.js v18.12.1

プロセスが 1 秒前に終了したため、'hello' が出力されないことがわかります。

期待どおりに動作していることを確認するには、.reject.resolve に変更します。

$ ノード -e "Promise.resolve(); setTimeout(() => console.log('hello'), 1000)" こんにちは###
したがって、LTS がサポートされているバージョンを使用して NodeJS アプリケーションを作成している場合は、必ずエラーを処理する必要があります。そうしないと、予期しないクラッシュが発生する危険があります。 

コードがブラウザ内でのみ実行される場合、障害を処理する必要があるかどうか疑問に思うかもしれません。結局のところ、ユーザーはコンソールを見ないので、何か悪いことが起こったことに気づきません。それで、誰が気にするでしょうか? ? 「コードのみ」の観点から見ると、あなたの考えは正しいですが、ユーザーは何か問題が発生したときにアプリケーションからのフィードバックを求めています。

次のシナリオを想像してください。Promise は、アプリケーションでユーザーが入力したデータを送信する API 呼び出しの結果を追跡します。何らかの理由で API 呼び出しが失敗した場合、アプリケーションは適切に応答して、何か問題が発生したことをユーザーに伝える必要があります。

これを処理する別の方法としては、アプリに無限読み込みスピナーが表示されたり、実際にはデータが正常に送信されていないのにユーザーがデータが正常に送信されたと思っていることが考えられます。いずれにしても、それは非常に悪く、壊れたユーザーエクスペリエンスです。

最後に、実際にはエラーを処理しない

.catch(e => { throw e })

のような処理を行います。もちろん、このコードはリンターを沈黙させますが、あなたがやっているのは、新しい拒否された Promise を作成し、それがコンソールに記録されるだけです。代わりに、何らかの方法でエラーをアプリケーションの UI に接続する必要があります。.catch(e => {alert(e); throw e }) のような単純なものの方が良いでしょう。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート