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

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

新規登録して質問してみよう
ただいま回答率
85.48%
EJS

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

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

JavaScript

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

Q&A

解決済

1回答

1107閲覧

node.jsでEJSにフラッシュメッセージが表示できない

kazu2021

総合スコア48

EJS

EJSは、JavaScript用のテンプレートエンジン。HTMLなどのテンプレートテキストにJavaScriptのロジックを記述することができます。また、変数・関数の実行をテンプレートテキスト内に埋め込むことも可能です。

Node.js

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

JavaScript

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

0グッド

0クリップ

投稿2022/05/17 06:18

編集2022/05/18 02:44

main.js

1app.use(expressSession({ 2 secret: "secret-passcode-tetsu", 3 resave: false, 4 saveUninitialized: false, 5 cookie: { 6 maxAge: 60*1000 //一分 7 } 8})); 9 10app.use(connectFlash()); 11 12app.use((req, res, next) => { 13 res.locals.flashMessages = req.flash(); 14** console.log(res.locals.flashMessages);**  ここのログを添付 15 next(); 16});

userContorller.js

1l~略~ 2.then(arraySearchResults => { 3 let arraySearchFilter = arraySearchResults.filter(searchResultsParam => { 4 return (searchResultsParam.statuses.length); 5 }); 6** if(!arraySearchFilter.length){ 7 8 return Promise.reject(new Error("検索結果がありません")); 9 }** 10 11 const sortArraySearchResults = arraySearchFilter.sort((a, b) => { 12 if (new Date(Date.parse(a.statuses[0].created_at)) < new Date(Date.parse(b.statuses[0].created_at))) return 1; 13 if (new Date(Date.parse(a.statuses[0].created_at)) > new Date(Date.parse(b.statuses[0].created_at))) return -1; 14 return 0 15 }); 16 res.locals.arraySearchResults = sortArraySearchResults; 17 next(); 18 19.catch(error => { 20 req.flash("errorMessage",error.toString()); 21 req.flash("test", "テスト"); 22 next(); 23~略~ 24 25 searchIndex: (req, res) => { 26 res.render("twitter/search"); 27 }

search.ejs

1 2<%= flashMessages.errorMessage %>

挙動がおかしくて
res.locals.flashMessagesにメッセージは格納できているようなのですが
node.jsのmain.jsでres.locals.flashMessagesをconsole.logで表示すると
プロンプトの最後に空のオブジェクトが表示されます。
このためにEJSでフラッシュメッセージが取得できていない感じなのですが・・・
数十回に一回のタイミングでEJSにフラッシュメッセージが表示されうまくいきます。
なぜ確率的にうまくいくのかわかりません。フラッシュメッセージに非同期通信が関連してるのでしょうか。
→userController.jsのPromise処理の中で検索結果が0だった場合にエラーのインスタンスをrejectしています。これをcatchするようにしてるのですがここの処理の構文が適切ではない気がします。調べてみます。

main.jsでのconsole.log(res.locals.flashMessages)ログ
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{ errorMessage: [ 'Error: 検索結果がありません' ], test: [ 'テスト' ] }
{}
{}

解決方法がありましたらご教示の程お願いいたします。

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

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

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

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

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

miyabi-sun

2022/05/17 09:13

この質問文だと読む気がしないので、 半角バッククォート(Shift+@キー)3個の行でくくってください。 編集画面で「コードの挿入」ボタンを駆使すればすぐ用意出来ます。 Markdownの記法を使いこなせればQiitaやZenn、GitHub等のサービスで サラッとかっこいいドキュメントを書けるようになるので頑張ってみてください。
kazu2021

2022/05/18 02:00

質問文がきれいにまとまりました。 ありがとうございます。 よろしくお願いいたします。
miyabi-sun

2022/05/18 03:46

ナイス、ぐっと読みやすくなりましたね。
guest

回答1

0

ベストアンサー

なるほど、状況を把握しました。
100%確実という保証は出来ませんが、多分これじゃないか?というものは見つかったので解説していきます。

js

1app.use((req, res, next) => { 2 res.locals.flashMessages = req.flash(); 3 console.log(res.locals.flashMessages); 4 next(); 5});

この使い方がよくありません。

ざっくりExpress.jsの実行の流れを解説すると
HTTPリクエストを受け取った時、上からヒットしたものを順次実行します。
例えばapp.getapp.postでパス指定でヒットしたらそこで終了
resの内容を使ってHTTPレスポンスを生成します。

この時重要なのは上からヒットしたものを順次実行の部分です。
app.useで指定したミドルウェアも全てヒット扱いです。
next関数を実行したらスルーして次にヒットしたものを使いますし、next関数を実行しなければ処理打ち切りでresを使ってHTTPレスポンスを作ります。

これの何がまずいかというと、
req.flash()が一度きりのメッセージを保管する目的で用意されているので、
関係ないリクエストで消費されてしまう懸念があることです。

もしリダイレクトや静的ファイル(CSS、JS、画像ファイル)のHTTPリクエストでも、
ヒットしたら全てこの処理を通過します。
そしてせっかくfrashに蓄えていた情報をそこで消費しちゃって、
HTMLファイルを作って返したい所で消費済なので何もデータがない。

これが原因でしょう。

解決策

  • app.useを使う時に第一引数に発火させたいパスを指定する
  • app.useではなく、ejs作っているapp.getの中でres.locals.flashMessages = req.flash();を実行する

推奨は後者ですね。
楽なのはわかりますが、わざわざミドルウェアでやるようなことじゃない。

まずパス指定まで含めるとapp.useで羅列するのは面倒だし漏れが出る。
トップページや一覧画面等の限定的なページのみがflashメッセージを必要とする為。
汎用的じゃないからapp.useは不適切じゃね?ってことですね。

投稿2022/05/18 04:08

miyabi-sun

総合スコア21158

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

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

kazu2021

2022/05/19 06:27

ご教示いただきましたapp,getの方でres.locals.flashMessages = req.flash();を実行したらエラーメッセがただしく表示されました。 またまさしくご指摘いただいた通りで静的ファイル(CSS、JS、画像ファイル)を main.jsのapp.use(express.static("public"));で処理しておりまして これをフラッシュメッセージのミドルウェアよりも上に置いたところ この方法でも正しくできました。 細かなところもなのですが全体の流れについても知識が抜け落ちておりまして たいへん勉強になりました。 誠にありがとうございます。
miyabi-sun

2022/05/20 00:48

> これをフラッシュメッセージのミドルウェアよりも上に置いたところ > この方法でも正しくできました。 おっ、これちゃんと確認してくれたんですね。流石! もし私がシステムを構築するのであれば想定であえて白黒つけると、 回答文のようにapp.getの中でやることを選択するでしょうね。 上に`app.use(express.static("public"));`を書いた場合 全てのPathをスルーした404エラーが紛れた時にやはりフラッシュの消費が懸念されます。 しかしWebサイトに辿り着いた後は上のURL欄を手打ちするなんて滅多にないことなので、 普通の使い方してる限り404エラーなんて出るわけないので僅差レベルだと思います。 自分のHTML作成時のミスでフラッシュ剥げたらヤだなぁって思うくらい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問