概要
ユーザーがアプリケーションを操作している間に例外やエラーが発生することは避けられません。発生する可能性のあるエラーを (故意または無意識のうちに) 処理する手段を選択するのは、ソフトウェア エンジニア次第です。 その結果、Express を使用して API を構築するバックエンド開発者は、便利で効率的で使いやすい API を構築するために努力していることに気が付きます。 最も重要なことは、堅牢なシステムを構築するような方法でエラーを処理することです。これは、開発時間、明らかなエラー、生産性の問題を削減し、ソフトウェア開発の成功またはスケーラビリティを決定するのに役立ちます。
エラー メッセージをログに記録する、エラーを抑制する、ユーザーにエラーを通知する、またはエラーを処理するコードを記述する必要がありますか? もう不思議ではない.
このガイドでは、Express アプリケーション用の堅牢なエラー処理コードベースを構築する方法を学習します。これは、アプリケーション エラーを検出し、最適なアクションを実行して実行時に適切に失敗したアプリケーションを回復するのに役立ちます。
注: Postman を使用して、デモで API をテストします。 でダウンロードできます。 ポストマンのダウンロードページ. または、単にブラウザのコマンドラインを使用することもできます curl
ツール、または使い慣れたその他のツールを使用できます。
エラー処理とは
ソフトウェア開発では、XNUMX 種類の例外があります。 オペレーショナル & プログラム的な.
- 実行時に操作エラーが発生する可能性があり、アプリケーションが突然終了するのを防ぐために、効率的なエラー処理メソッドを通じてこれらの例外を適切に処理する必要があります。
- プログラム例外は、例外状態が発生したときに、プログラマーによって手動でスローされます。
操作上の例外は「予期しないが予見された」例外 (範囲外のインデックスへのアクセスなど) と考えることができ、プログラムの例外は「予期され予見された」例外 (数値書式設定の例外など) と考えることができます。
例外処理は、プログラム内の欠陥を見つけて修正するために使用される手順です。 エラー処理は、発生したエラーのタイプとエラーが発生したスタックを含むメッセージを送信します。
注: コンピューター サイエンスでは、例外は回復可能であり、通常は実行時の操作上の問題またはプログラム上の問題から発生します。 エラーは通常、ハードウェアの制限、接続の問題、メモリ不足などの外部要因から発生します。 JavaScript では、これらの用語はしばしば同じ意味で使用され、カスタム例外は Error
クラス。 ザ・ Error
クラス自体がエラーと例外の両方を表します。
Express では、例外処理は、Express が同期および非同期の例外をキャッチして処理するように設定する方法を指します。 Express での例外処理の利点は、開発者が独自の例外ハンドラーを作成する必要がないことです。 Express にはデフォルトの例外ハンドラが付属しています。 例外ハンドラは、エラーを特定してユーザーに報告するのに役立ちます。 また、さまざまな修復戦略を提供し、それらを実装して例外を軽減します。
これらは内部で行われている多くのことのように見えるかもしれませんが、Express の例外処理は、プログラムの全体的なプロセスを遅くしたり、その実行を一時停止したりしません。
Express での例外処理について
Express に付属するデフォルトのエラー ハンドラーを使用すると、ルート ハンドラーでエラーを自動的にキャッチするのに役立つ一連のミドルウェア関数を手に入れることができます。 近いうちに、Express アプリで適切なエラーを返す方法と機密情報を漏らさない方法について、理論を実践するプロジェクトを作成します。
Express でのミドルウェア機能の定義
エラー処理ミドルウェア関数は、 Error
object を最初の入力パラメータとして指定し、その後に他のミドルウェア関数のデフォルト パラメータを指定します。 request
, response
, next
を選択します。 next()
関数は、現在のすべてのミドルウェアをルーターの次のエラー ハンドラーにスキップします。
Express でのエラー処理の設定
ターミナルで次のコマンドを実行して、Node and Express アプリを作成します。
$ mkdir error-handling-express
新しく作成されたフォルダーで、新しい Node プロジェクトを初期化しましょう。
$ cd error-handling-express && npm init -y
これにより、 package.json
私たちのフォルダのファイル。
Node アプリで Express サーバーを作成するには、 express
パッケージ、 dotenv
環境変数を自動的にロードするため .env
ファイルに入れる process.env
オブジェクト、および nodemon
ファイルの変更がディレクトリに記録されている場合、ノード アプリを再起動します。
$ npm install express dotenv nodemon
次に、を作成します app.js
アプリのインデックス ファイルとして機能するプロジェクト フォルダー内のファイル。
Express アプリに必要なすべての依存関係をインストールしたので、アプリを読み取るスクリプトを設定する必要があります。 package.json
ファイル。 それを達成するために、 package.json
ファイル、そのように scripts
オブジェクトは次のようになります。
"scripts": {
"start": "nodemon app.js"
},
または、使用をスキップできます nodemon
、そして node app.js
を代わりにお使いください。
Express サーバーのセットアップ
サーバーをセットアップするには、まずさまざまなパッケージをにインポートする必要があります app.js
. また、 .env
プロジェクト ディレクトリのファイル – アプリケーションのすべての環境変数を保存します。
const express = require('express')
require('dotenv').config
PORT=4000
アプリのポート番号を定義しました .env
によって読み込まれ、読み込まれます。 dotenv
、後でアクセスできます。
Express サーバーの初期化
ここで、Express サーバーを初期化し、アプリがアプリのポート番号をリッスンするようにする必要があります。また、テスト ルートへのリクエストも送信します。 /test
. 更新しましょう app.js
、 import ステートメントの下:
const app = express();
const port = process.env.PORT || 4000;
app.get("/test", async (req, res) => {
return res.status(200).json({ success: true });
});
app.listen(port, () => {
console.log(`Server is running at port ${port}`);
});
ここからは、発生する可能性のある操作エラーのさまざまなユース ケースを Express で処理する方法を学習します。
Express での Not Found エラーの処理
ユーザーのデータベースからすべてのユーザーを取得する必要があるとします。ロジックを try/catch
ブロック – に投影される可能性のあるエラーをキャッチすることを望んでいます catch
ブロック:
const getUser = () => undefined;
app.get("/get-user", async (req, res) => {
try {
const user = getUser();
if (!user) {
throw new Error('User not found');
}
} catch (error) {
console.log(error);
res.status(400).send(error.message)
}
return res.status(200).json({
success: true
});
});
この結果:
User not found
ここで、このリクエストが行われ (Postman を使用してテストできます)、データベースにユーザーが存在しない場合、クライアントは「ユーザーが見つかりません」というエラー メッセージを受け取ります。 また、コンソールにもエラーが記録されていることに気付くでしょう。
エラー ハンドラ ミドルウェアによるエラー処理の最適化
定義されたすべてのルートの最後に来るエラー ハンドラー ミドルウェアを作成することで開発を最適化できます。これにより、ルートの XNUMX つでエラーがスローされた場合、Express は自動的に次のミドルウェアを見て、リストを下に移動し続けます。エラーハンドラに到達するまで。 エラー ハンドラーはエラーを処理し、クライアントに応答を返します。
ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!
開始するには、というフォルダーを作成します。 middleware
プロジェクト ディレクトリに、このフォルダに次のファイルを作成します。 errorHandler.js
エラーハンドラを定義します:
const errorHandler = (error, req, res, next) => {
console.log(error);
res.status(400).send(error.message);
}
module.exports = errorHandler;
ミドルウェア関数では、これが基本的なミドルウェア関数ではなく、エラー ハンドラーであることを Express に認識させます。 error
3 つの基本パラメーターの前のパラメーター。
ここで、デモでエラー ハンドラを使用します。 app.js
以下に示すように、エラー ハンドラー ミドルウェアを使用して、ユーザーのフェッチの初期エラーを処理します。
const getUser = () => undefined;
app.get("/get-user", async (req, res, next) => {
try {
const user = getUser();
if (!user) {
throw new Error("User not found");
}
} catch (error) {
return next(error);
}
});
app.use(errorHandler);
の周りに抽象化を作成することで、コードをさらに最適化できます。 try/catch
論理。 これを実現するには、プロジェクト ディレクトリに新しいフォルダーを作成します。 utils
、そしてその中に、というファイルを作成します tryCatch.js
.
を抽象化するには try-catch
ロジック – 別の関数を受け入れる関数を定義できます ( コントローラ) をパラメータとして、 async
を保持する関数 try/catch
受信したコントローラーの場合。
コントローラでエラーが発生した場合、 catch
ブロックし、次の関数が呼び出されます。
const tryCatch = (controller) => async (req, res, next) => {
try {
await controller(req, res);
} catch (error) {
return next(error);
}
};
module.exports = tryCatch;
try/catch
抽象化をスキップすることで、コードをリファクタリングしてより簡潔にすることができます。 try-catch
句でユーザーをフェッチするときに明示的に app.js
:
const getUser = () => undefined;
app.get(
"/get-user",
tryCatch(async (req, res) => {
const user = getUser();
if (!user) {
throw new Error("User not found");
}
res.status(400).send(error.message);
})
);
try-catch ロジックの抽象化に成功し、コードは以前と同じように機能します。
Express での検証エラーの処理
このデモでは、Express アプリにログイン用の新しいルートを作成します。これは、ログイン時にユーザー ID を検証するためです。まず、 joi
要件を適用できるスキーマの作成に役立つパッケージ:
$ npm i joi
次に、スキーマを作成します。 Joi.object
また、 userId
これは数字である必要があり、必須です。つまり、リクエストはユーザー ID を持つオブジェクトと一致する必要があります。
使用できます validate()
スキーマ オブジェクトのメソッドを使用して、すべての入力をスキーマに対して検証します。
const schema = Joi.object({
userId: Joi.number().required(),
});
app.post(
"/login",
tryCatch(async (req, res) => {
const {error, value} = schema.validate({});
if (error) throw error;
})
);
空のオブジェクトが渡された場合 validate()
メソッドを使用すると、エラーは適切に処理され、エラー メッセージがクライアントに送信されます。
コンソールでは、 details
必要に応じてユーザーに通知できるエラーに関するさまざまな詳細を含む配列。
検証エラーごとに適切なエラーの詳細を渡すような方法で検証エラーを具体的に処理するには、エラー ハンドラー ミドルウェアをリファクタリングできます。
const errorHandler = (error, req, res, next) => {
console.log(error);
if (error.name === "ValidationError") {
return res.status(400).send({
type: "ValidationError",
details: error.details,
});
}
res.status(400).send(error.message);
};
module.exports = errorHandler;
errorHandler.js
に空のオブジェクトを渡して同じリクエストを行うと、カスタマイズされました。 validate()
方法:
これで、より読みやすく使いやすい方法でメッセージを返すカスタマイズされたオブジェクトにアクセスできるようになりました。 このようにして、入ってくるエラーの種類に基づいて、さまざまな種類のエラーを送信して処理することができます。
まとめ
このガイドでは、デフォルトでの同期および非同期コードの処理方法、独自のエラー クラスの作成方法、カスタム エラー処理ミドルウェア関数の作成方法、提供方法など、Express.js のエラー処理のあらゆる側面について説明しました。 next
最後のキャッチハンドラーとして
そこにあるすべてのタスクと同様に、効果的なエラー処理を含む開発中のベスト プラクティスもあります。今日、Express アプリで堅牢な方法でエラーを処理する方法を学びました。
エラーを適切に処理することは、バグやエラーを簡単に見つけて開発時間を短縮するだけでなく、大規模なアプリケーション用の堅牢なコードベースを開発することも意味します。 このガイドでは、操作エラーを処理するためのミドルウェアをセットアップする方法を見てきました。 エラー処理を改善するその他の方法には、スタック トレースを送信しない、キャッチされていない例外を処理するためにプロセスを適切に停止する、適切なエラー メッセージを提供する、エラー ログを送信する、および Error
とに提供されます。
このチュートリアルで使用した例が皆さんにとって楽しいものであったことを願っています。 エラー管理に関して、現実の世界で使用する Express アプリケーションを作成する際に遭遇する可能性のあるさまざまなシナリオについて説明しました。 見逃したものがある場合はお知らせください。 それは私たちに利益をもたらし、私がより多くを学ぶのにも役立ちます. 良い一日を。読んでくれてありがとう。
この記事で使用されているすべてのソース コードを参照できます。 githubの.