#はじめに
現在とあるチームプロジェクトにおいてフロント(Vue.js)を担当しております。しかしバックエンドをNode.jsで組んでおり、ちょくちょくそちら側も勉強しております。
とても親切に優しく書かれているので、初学者の方にはお勧めですねー。
チャプター3で「超簡単掲示板を作ろう」とあるのですが、個人的に追加で機能を実装しながら遊んでいましたところ、とある問題に気づきました。
それが、「フォームの二重送信問題」
特に「ページリロード時に発生する」ものについてです。
対策としては、PRGパターンの活用や、トークンの発行など色々あるのですが、
調べても調べても出てくるのはPHPにおける対策例ばかり。
確かに以前私もPHPを使ったことがあるので、そちらについては分かるのですが、今回はNode使ってるし、しかも送信後の表示ページは元のホーム画面と同じこともあり、ずっとどうしていいかわからず悩んでおりました。(私の知識不足が大きな要因ではありますが。。)
<フォーム部分のコード>
actionで"/"記述することで、送信後のリクエストページを同じページに戻らせており、POSTメソッドを使用しています。
そして、**「こんにちは!」**と送信してみます。
すると、無事に一番上にきちんと表示されました。
(今は私の名前でログインしているので、自動でID名は藤井となります)
検証ツールから「ネットワーク」を見て、さらに「ヘッダー」部分をみると、きちんと「Form Data」のところにidとmsgが表示されています。
しかし、これが問題でした。
送信完了後にここの「Form Data」が残ることにより、ページを再読み込みした時に何度も送信されてしまうのです。
ページの更新ボタンを押して見ます。
ほら、このように結果として二重送信されてしまっています。。。。
#解決策
Ajaxによる非同期通信が一番簡単でいいのではないかと、メンターからアドバイスを頂き、素直にそうすることに。まあ、それが一番簡単だよね。
しかし、気づきました。jQueryが必要やーーん。
素のJSでいじっていたので、どうしようか悩んで調べていたところ、行き着いたのがこちらの記事。脱jQuery $.ajax()
とても丁寧に解説されており、早速取り入れて見ることに。
ここで登場するのが、XMLHttpRequest
「クライアントとサーバー間でデータをやり取りするためのAPI」だそうです。
まあ、詳しくはググってみてくださいww
そんなことより早速実装してみました。
ひとまず、先ほどのフォーム部分に、自動でフォーム送信が起こらない
ように**追加①**を入れました。onsubmit = "return false"
と入れるだけです。
その次に、送信ボタンに対してonclick="関数名"
**追加②**を入れて、送信処理を関数内で実行するようにします。ここではsubmitForm()
としました。
次にscript
タグの中で処理を書きます。。
先ほどの送信ボタンを押した時に発火するsubmitForm()
をここで定義します。
上の画像に各役割の説明を入れました。
通信成功時の処理は特に必要ないので、空にしておき、完了時にページの再読み込みを行うようにしました。非同期通信ですので、ページのリロードを行わないと、追加処理が画面に反映されません。
そして、最後にmyXml.open()
と書くことで、フォーム送信処理をここで初めて定義しています。ここでは、POSTメソッドで、同じ画面に戻りたいのでURLは/
と書いています。
最後のif分はフォームの中身が空でない場合にのみ、送信処理がされるようにしました。
再度検証
一通り再設定は終わったので、再度試してみます。
今回は**「お寿司がいいです!」**と送ってみます。
おーー!ちゃんと送信されました。
ネットワークのHeadersを見ても、Formdataは見当たりません。よし!
そして、リロードしてみます。
ポチッとな。
おおーーー!二重送信されていない!
無事にXMLHttpRequestが働いているぞ。感動。
#最後に
二重送信の対策の一つとして、素のJavaScriptで書く場合はこのやり方が簡単な方法だと思いました。同じような問題に詰まっている方がいらっしゃいましたら、この記事が何かしらの助けになれば幸いです。
#参照
XMLHttpRequest.readyState: ReadyStateに当てる番号の役割について理解
XMLHttpRequest についてのメモ:メソッドやプロパティについて詳しく表になっています!
Node.js超入門:Node.jsのためにいま利用している参考書