Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

ExpressのAsync Errorのハンドリング

$
0
0

問題点: asyncでリクエストハンドラを定義して処理中に例外が発生してもハンドリングできない

たとえば、http://localhost:3333/notfoundrouteのように存在しないルートにアクセスしたら、ステータスコード:404、ボディコンテンツにRoute not foundを返したい場合において、以下のコードを実装したとする。

importexpress,{Request,Response,NextFunction}from"express";constapp=express();app.get("/hi",(req,res)=>{res.send("Say hi");});// 問題の箇所// ここで例外を発生させるapp.get("*",async(req,res)=>{thrownewError("Route not found");});// エラーを扱うためのハンドラapp.use((err:Error,req:Request,res:Response,next:NextFunction)=>{returnres.status(404).send(err.message);});app.listen(3333,()=>console.log("Listenin on port 3333"));

しかし、実行結果としては、レスポンスが返ってこない

curl -v localhost:3333/notfoundroute
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3333 (#0)
> GET /notfoundroute HTTP/1.1
> Host: localhost:3333
> User-Agent: curl/7.64.1
> Accept: */*
>

サーバ側のログ出力も以下のようになっていて、Promiseを上手く扱えていない。

(node:11743) UnhandledPromiseRejectionWarning: Error: Route not found
...
(node:11743) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:11743) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

解決策1: nextで例外をラップする。

問題の箇所を以下のように変更する。

...app.get("*",async(req,res,next)=>{next(newError("Route not found"));});...

実行結果は、期待した結果が得られている。

curl -v localhost:3333/notfoundroute
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3333 (#0)
> GET /notfoundroute HTTP/1.1
> Host: localhost:3333
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 15
< ETag: W/"f-f4JcZAomq7bAiiL2cdorz+qCRSw"
< Date: Tue, 05 May 2020 07:00:15 GMT
< Connection: keep-alive
< 
* Connection #0 to host localhost left intact
Route not found* Closing connection 0

解決策2: express-async-errorsパッケージをインポートする。

必要なパッケージをインストールする。

yarn add express-async-errors

問題の箇所は変更しなくてもよいが、express-async-errorsをインポートする。

importexpress,{Request,Response,NextFunction}from"express";import"express-async-errors";...app.get("*",async(req,res)=>{thrownewError("Route not found");});...

こちらも実行結果は、期待した結果が得られている。

curl -v localhost:3333/notfoundroute
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3333 (#0)
> GET /notfoundroute HTTP/1.1
> Host: localhost:3333
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 15
< ETag: W/"f-f4JcZAomq7bAiiL2cdorz+qCRSw"
< Date: Tue, 05 May 2020 07:00:15 GMT
< Connection: keep-alive
< 
* Connection #0 to host localhost left intact
Route not found* Closing connection 0

Viewing all articles
Browse latest Browse all 8691

Trending Articles