質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

5回答

5690閲覧

return res.send()とres.send()の違いについて

maskmelon

総合スコア63

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/07/13 06:33

JavaScript

1app.get('/users/:id', (req, res) => { 2 const _id = req.params.id 3 User.findById(_id).then((user) => { 4 if (!user) { 5 return res.status(404).send() 6 } 7 res.send(user) 8 }).catch((e) => { 9 res.status(500).send() 10 }) 11})

if文の中でreturnが使われており、if文内の処理を実行させるとres.status(404).send()が実行されますが、これは普通にres.status(404).send()と書くのと何か違いがあるのでしょうか?

意図があってわざわざreturnを加えているとは思うのですが、どのような意図なのか分かりませんでした。

分かる方いらっしゃいましたらぜひご教授ください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

問題の部分だけを展開します。

js

1function (user) { 2 if (!user) { 3 return res.status(404).send() 4 } 5 res.send(user) 6}

これはガード節と呼ばれる書き方です。
参考記事: 初心者向け。覚えておきたい 「ガード節」という書き方。 - Qiita

普通に書くとこうなります。

js

1function (user) { 2 if (!user) { 3 res.status(404).send() 4 } else { 5 res.send(user) 6 } 7}

このif-elseは処理が複雑になればなるほどインデントがネストされていき、
非常に読みづらくなってしまいます。
そこで探索を早期に打ち切るのがガード節というテクニックです。


Node.jsのExpress.js系だと思われますが、
Express.jsのres.sendメソッドは2回実行するとエラーになります。
なのでelse側は実行させてはいけません。

ifに入ったものを早期に終了させるreturnが必要不可欠となります。

js

1function (user) { 2 if (!user) { 3 res.status(404).send() 4 return // 返り値なしで処理を打ち切る明示的なreturn 5 } 6 res.send(user) 7}

returnによる返り値は基本的に後で使うと明示した方が良いのは事実ですが、
別に不具合が発生しないとわかっている箇所ならば問題ありません。
今回はUser.findById(_id).then(fn1).catch(fn2)のfn1の部分で実行しますよと記述されていますから、返り値は誰も使って居ないのが一目瞭然ですね。

まぁ、行数が減ると読む時に楽なんで、
私が自分一人のプロジェクトでif文で1行だけの時は{}すら省略出来るのでこんな感じで横着してます。

js

1function (user) { 2 if (!user) return res.status(404).send() 3 res.send(user) 4}

投稿2020/07/13 07:16

miyabi-sun

総合スコア21203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hentaiman

2020/07/13 09:19

> 非常に読みづらくなってしまいます。 return複数ってどうなんでしょうね 個人的にはreturnはひとつ(java的な考え)の方が読み易いと思ってます
miyabi-sun

2020/07/13 09:36 編集

> return複数ってどうなんでしょうね リーダブルコードという書籍で推奨されている手法です。 例えば数学の場面で、「フィボナッチ数列の2以下は1と決めますよ」という独自ルールに対応したり、 数学的帰納法を使う時にn=1の場合はXであるみたいな回答をまず定義! やっている事はこれと同じです。 効果も結構あり、同意する人もそれなりに多いですね。 > 個人的にはreturnはひとつ(java的な考え)の方が読み易いと思ってます あー、私のJava界出身の元同僚ともそういう会話になった事ありますね。 「俺さ、リーダブルコードは良いと思うんだけどガード節は絶対に納得できねえ!」 これは最終的にはコーディング規約で、 プロジェクトメンバーの同意の元合意して従うようにすべきです。 その時の同僚の主張は「このプロジェクトはJSだから」で負けました。 関数・メソッド末尾のreturnも一貫していればキレイだと思います。 もちろん超長いif-elseはバッドプラクティスなので、 どうするねんはその場その場でじっくり考えるべきでしょうね。 DIちゃんとやれとかの話とかに飛び火するかも? まぁ、今回は「ガード節」に対して「これ何?」って質問なので、 超長いif-elseのバッドプラクティスを交えて回答したって事でよろしくです。
hentaiman

2020/07/13 09:47 編集

>超長いif-elseのバッドプラクティスを交えて回答したって事でよろしくです。 はい 返答頂いたついでと言ってはなんですが質問させてください。 単純に疑問ですが、処理を下から(return側)追う事はないんですか?無いとしたらunittest等が完璧で下から追わなければならない状況にはならないようにしているのでしょうか? 自分がreturnひとつが良い理由は単純に下からも処理が追いやすいからです。java出身で無いので自分も元々はreturn複数書いてました。 >「俺さ、リーダブルコードは良いと思うんだけどガード節は絶対に納得できねえ!」 理由が感情論だったんですか?同僚の技術力が特出してない限りは多数決次第でしょうねえ
miyabi-sun

2020/07/13 10:38

リーダブルコードでは今からやることにシンプルな名前を付けて、 それを読んで処理内容を容易に想像でき、ひと目で中身も理解出来るように書けと説いています。 関数・メソッド名がトンチンカンだから、1行1行精査していくような古文書の翻訳みたいなことになってるんでしょ?というロジックです。 私はこの思想に感化されて実践しはじめましたが、 かなり効果ありましたね。下から読みつつ机上デバッグはめったにやってません。 もしリーダブルコードがまだなら是非読んでみてください。 ベストセラーなだけはあります。 > 理由が感情論だったんですか? 後輩の新入社員に休憩時間中「リーダブルコード読め」とパワハラしていた所に その同僚と一緒になったという一幕です。 その同僚は実務でもガード説が必要な場面に遭遇しないように、 安易な関数・メソッド実行をせずに、その上の段階で弾いていましたね。 初期処理って大抵の場合、横着して初期処理サボって、1個の関数・メソッドに詰め込んだだけですから。 なので感情論「俺はJava畑だからガード節は絶対に許せない」 そのために設計をしっかり練って立ち向かう。 原理と手段をよく読んで、それでちゃんと素敵な回答を出せているならそれで良いと思います。
hentaiman

2020/07/13 11:02

> 1行1行精査していくような古文書の翻訳みたいなことになってるんでしょ?というロジックです。 > 下から読みつつ机上デバッグはめったにやってません。 > 1個の関数・メソッドに詰め込んだだけですから これだけ見ると関数型言語使えばいいじゃんと思っちゃいましたが、WEBフロントのjavascriptは避けられないですね 書籍は今度本屋でチェックしてみようと思います。 コメントありがとうございました。 回答者が見るかもという事で少しコメント追加しますが、複数return自体を否定する意見ではありません。フレームワークの中身を読めば複数リターンにはそれなりに見かけるし、実際に読み易いです。多分リーダブルコードの元になった考え方が使われているのでしょう。
standard-soft

2020/07/13 12:52

早期returnは読みやすいです。 知る前と知ったあとでは、だいぶコードの読みやすさがあがった気がします。 ガード節もいいですよね。防御的プログラミングとか契約プログラミングと呼ばれる手法で不具合が明らかに減ってくるから愛用(?)しています。
miyabi-sun

2020/07/13 12:59

> これだけ見ると関数型言語使えばいいじゃん これはそうですね。 仕事ではClojureScript、家ではLiveScriptを使ってます。 知り合いはElmですね。 いろんなAltJSがあったのに、TypeScript一強状態が本当に悲しい。
think49

2020/07/13 13:56 編集

@hentaiman さん > 個人的にはreturnはひとつ(java的な考え)の方が読み易いと思ってます その感覚は、共感できます。 > 単純に疑問ですが、処理を下から(return側)追う事はないんですか? これも理解できます。 入口も出口も一つだから追いかけやすいのですよね。 私は構造化プログラミングから入り、Array.isArrayの仕様を読んで、「ガード節(早期リターン)」に転向した口ですが、アルゴリズムの習得に苦労した程度でコードの可読性が上がったようには感じませんでした。 出口を複数にすると、全体把握がしづらくなります。 出口を一つにすると、一つの出口に向けて一貫性のあるコードを書く必要があるので、全体把握の可読性が上がる、というのが私の評価です。 コードの内容によっては、最適化の過程でコードがかなり変わります。 『リーダブルコード』は名著ですが、一意見としての目線で読むのが良いと私は思います。
think49

2020/07/13 13:59

ちなみに、私のお勧めは「構造化プログラミング」と「ガード節」をケースバイケースで使い分ける、です。 どちらかが一方的に良い関係性ではないので、性質を把握した上で使い分けるのが賢いと思います。
hentaiman

2020/07/13 15:55 編集

> 知り合いはElmですね。 Elmもありましたね。すっかり忘れてました ガード節というのは「javaのオーバーロード+ifのような物の複合(elixir仕様)」を考えてたので、こういうのをガード節と言うとは知らなかった ※正確には違いますが > 私は構造化プログラミングから入り、Array.isArrayの仕様を読んで、「ガード節(早期リターン)」に転向> 『リーダブルコード』は名著ですが、一意見としての目線で読むのが良いと私は思います。 ある程度書けるようになった人がその手の書籍から追加で知識を得るのがベターという意味で同意です > 「ガード節」をケースバイケースで使い分ける フレームワークのソースを参考にしてるので多少は使い分ける事もありますが、やはり基本的にはreturnひとつですね 思想がブレブレでその時の気分でコロコロ書き方変わるのはNGだと思います、「single return vs multiple returns」の思想自体は個人やチームの好きにすればいいかなと思います > コードの内容によっては、最適化の過程でコードがかなり変わります。 バリデーションを自作するなら早期リターンが良いですね
AkitoshiManabe

2020/07/13 21:48

質問者様には、熟読してほしい回答に感じます。 ソースを失念しており、説得力に欠けてしまうのですが、最初の意図は「JavaScript は他の言語に比べて処理速度が遅いので、パフォーマンスチューニングの目的で早期リターンが使われ始めた。」と記憶しております。
standard-soft

2020/07/14 03:09

リーダブルコードが早期リターンの普及に一役買っている感じはしますが、JavaScriptに限らず早期リターンは有効ですよ。ネストの深いifを書かなくて済みます。
hentaiman

2020/07/14 06:20 編集

先のコメントでは否定する意見ではありませんと書いたけど、ネストに言及されてるので少し補足 飽くまでも回答者の同僚さんと同じように早期リターンせずともネストの深くないコード書けるようになればの話です。「早期リターンしないとネストが深くなる人」の解決方法が早期リターンになってしまうならやはり早期リターンはおすすめしません。使っても使わなくても深いネストにならずにコード書ける人なら使っても良いという程度です。 但しこれは一意見なので、他の人の意見も踏まえて質問者自身で判断してください
maskmelon

2020/07/14 14:40 編集

回答、コメントくださった皆様ありがとうございます。 まず、質問の趣旨だったreturnの意図については、後続の処理を回避するためのガード節であるということが理解できました。 コメントの議論の内容を全て把握できたわけではありませんが、早期リターンを採用することのメリットデメリットについて理解が深まったように思います。大変勉強になりました。
guest

0

質問の意図

私はNode.jsに詳しくありませんが、既存の回答の方向性に疑問を感じるため、あえて回答します。

if文の中でreturnが使われており、if文内の処理を実行させるとres.status(404).send()が実行されますが、これは普通にres.status(404).send()と書くのと何か違いがあるのでしょうか?

意図があってわざわざreturnを加えているとは思うのですが、どのような意図なのか分かりませんでした。

ここでいう「意図」とは、

JavaScript

1if (!user) { 2 return res.status(404).send() 3}

JavaScript

1return res.status(404).send()

の違いは何ですか、と解釈しました。

「ガード節を使う意図」は、各コードの挙動を理解していることが前提ですが、その前提に至っていないと感じます。

Node.js Document

検索して、
https://www.google.com/search?q=site%3Anodejs.org+status+send
getメソッドのドキュメントを読んで、
https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_http_get_options_callback

The callback is invoked with a single argument that is an instance of http.IncomingMessage.

に、うなる

  • 質問コードの第二引数 res はどこに?
  • 質問コードの第一引数 req を利用してststusCodeがとれそうな気が…

Express.js

発想を変えて、"res.status-404" て検索すると、Express.jsのドキュメントがHIT
https://www.google.com/search?q=res.status-404
ようやく、statusメソッドのドキュメントを発見する。

https://expressjs.com/ja/4x/api.html

res.send([body])
Sends the HTTP response.

The body parameter can be a Buffer object, a String, an object, or an Array. For example:

res.status(code)
Sets the HTTP status for the response. It is a chainable alias of Node’s response.statusCode.

質問コードを読む

質問コードは、

JavaScript

1if (!user) { 2 return res.status(404).send() 3} 4res.send(user)

Express.jsのドキュメントに従い、

  1. 変数 user がfalsyのとき、「HTTPステークスコード=404」「body=空」を返す
  2. それ以外は、「body=変数 user 値」を返す

という挙動になります。

ガード節(早期リターン)を使うべきか

ガード節(早期リターン)を使うべき論については、私は懐疑的な立場です。
この場合、

JavaScript

1return user ? res.send(user) : res.status(404).send();

このように、後期リターンに変更しても、何も問題がありません。


早期リターンが速いという見解もありましたが、「変数 user がtruyhy/falsyのどちらの割合が多いか」の結果を見て、評価順を判断するのが妥当と考えます。

設計や要件にもよると思いますが、ユーザが発見される挙動を正とするなら、この場合は後期リターン型を私は採用します。

Re: __stsh さん

投稿2020/07/14 04:05

think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maskmelon

2020/07/14 14:52 編集

ドキュメントの追い方、参考になりました。 三項演算子を用いて後期リターンするやり方もあるのですね。 確かにメインの処理が先に来る方が違和感なく感じられます。
hentaiman

2020/07/14 16:41 編集

書籍も読まずすいませんがちょっと質問させてください。 > 早期リターンが速いという見解もありましたが、「変数 user がtruyhy/falsyのどちらの割合が多いか」の結果を見て、評価順を判断するのが妥当と考えます。 これはリーダブルコードに書いてあった考え方ですか?書籍読めば分かるだろう事を質問してしまってすみません。
think49

2020/07/14 23:22 編集

@hentaiman さん 「早期リターンが速い」はAkitoshiManabeさんのコメントです。 > ソースを失念しており、説得力に欠けてしまうのですが、最初の意図は「JavaScript は他の言語に比べて処理速度が遅いので、パフォーマンスチューニングの目的で早期リターンが使われ始めた。」と記憶しております。
hentaiman

2020/07/14 23:30

コメントが不足してました、そちらではなく >「変数 user がtruyhy/falsyのどちらの割合が多いか」の結果を見て、評価順を判断するのが妥当と考えます。 ここに対しての質問です
think49

2020/07/15 04:00

@hentaiman さん そこは私個人のパフォーマンスに対する考え方ですね。 今回のような単純例だと説明が難しいので、後程、回答に例示コードを加えておきます。 低評価された方へ 差し支えなければ、低評価理由を教えて下さい。 「質問の意図」は主観があるので引っかかりそうですが、質問者さんからは指摘がなく、原因に心当たりがない状況です。
hentaiman

2020/07/15 04:59

いえ、大丈夫です。ありがとうございました。
guest

0

この return は処理をそこで打ち切りたいからつけてるだけですね

returnがないと、後続の処理が流れてしまって意図しない結果になるのでしょう。
このコードであれば、 !userということなので、多分ログインしてない状態であれば
404を返して終わり。 という意味かと思います。

投稿2020/07/13 06:52

YakumoSaki

総合スコア2027

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maskmelon

2020/07/14 14:51

回答ありがとうございます。参考になりました。
guest

0

回答、みなさんのおっしゃるとおりです。

if (xxx) { return res.status(404).send(); }

上記は、下記の意味ですよね。

if (xxx) { res.status(404).send() return; }

上の書き方は短くかけるメリットあるのですが returnに戻り値が何もないことが明示的ではないので、戻り値はなんなんだろう?と迷いを生むために、よい書き方ではないと思います。

また、こんな記事もありました。

if文の括弧は省略できるなら省略するのは是か非か | バシャログ。
http://bashalog.c-brains.jp/09/08/05-004630.php

投稿2020/07/13 09:09

編集2020/07/13 09:10
standard-soft

総合スコア197

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

nodeはいまいちわかりませんがreturnをつけると
コールバック関数においてその後ろに処理が流れない効果が期待できます。

投稿2020/07/13 06:35

編集2020/07/13 06:36
yambejp

総合スコア116724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maskmelon

2020/07/14 14:51

回答ありがとうございます。参考になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問