fetch(POST)で送った同時に次のページに遷移させたい

ベストプラクティスでいうと下記のように作り変えましょう。

  • connect.phpは2通りの入口を作る
    • POST: 入力値をセッションに保存するだけ
    • GET: セッションの値を表示する
  • fetchでconnect.phpへ向かってPOST通信を一度投げて、.then((result) => console.log(result)).then(=> window.location.href = 'http://localhost/connect.php';)に書き換える

んで、なんでこれが最善なのか?に関して判断材料を共有していきます。


JavaScriptのコードで使用しているfetchはFetchAPIのことです。
今閲覧中のページはそのまんま開きっぱなしにした状態のまま、裏でこっそりHTTP通信を発射して情報を持ち帰る機能を指します。

「fetchを使ったけどページ遷移できません!」と言われても至極当然の話で、
ページ遷移したくないからページ遷移せずに情報を追加で持って帰ってくる機能に何を期待してるんだ?って話になるわけですよ。


次、connect.phpはPOSTメソッドでリクエストを待ち構えてますが、
ChromeやFirefox等のブラウザで扱う場合成約があります。
(この辺の知識はRESTfulで勉強してください)

普段我々がWebブラウザを開いてWebサイト・Webページを表示する時って
情報を受け取りたいからWebサイトへアクセスしてるわけですよ。
つまり基本的には全てGET。

SNSや掲示板、後はAmazon等のショッピング等でこちらから情報を送信して保存してもらいたい。
そういう時に使う通信がPOSTになります。

JavaScriptからWebブラウザを操ってPOST通信する方法は基本的には以下の2パターンしかありません。

  • FetchAPI (Ajax) を利用して、裏で勝手にPOST通信を行う方法
  • CSSで非表示にしたダミーのフォームをDOM上に展開しておき、そのフォームをJavaScriptの機能でsubmitする

実際Webブラウザで単にPOST通信するって事はできないんですよね、
アドレス欄に入力してページ遷移した時は絶対にGETです。
window.location.href = 'http://localhost/connect.php';はブラウザのアドレス欄を弄ってるのと同じでGET。

POST通信してないんだから結果が得られるわけないですね。
connect.phpはPOST通信を受け取ったら情報を保存&画面表示するけど、GET通信だったら何も保存しないし表示もしない作りになってるんだから。


じゃあ裏でフォーム部品作って<form style="display: none;">みたいなの作って
JavaScriptのDOM操作機能を使ってサブミットすりゃええやん。

これもWebエンジニアとしては推奨できません。
理由はF5キーでページをリロードした時や、ブラウザバック・フォワード機能を使った時に不整合が出るためです。

POST通信しますよーという状態になっているフォーム部品をサブミットしてページ遷移した場合、
遷移後のページはPOST通信で受け取ったものになります。
その状態でページをリロードすると、再度同じPOST通信を発射しながらページリロードを試みることになります。

これがSNSや掲示板サイトでは同じ投稿内容を2重送信しようとした、
ショッピングサイトでは同じものを2度購入しようとしたという風に受け取れるわけですね。
もしAmazonで注文した商品が2個届いて、2倍の値段請求されたらどうします?私だったらブチギレますね。

なので、POST通信を受け取ったら、そのままHTMLを返すなんてしません。
fetch前提ならば、受け取ったよー保存したよーというメッセージを返して終わり。
フォームでページ遷移する時は、connect.phpのような受ける側で保存した後に、リダイレクト機能を使ってGETでブラウザに別の表示専用のURLに強制送還してそっちでHTMLや結果のメッセージを表示する。

こういう風にすると、リロードやブラウザバック等の機能を使われても2重送信が発生してしまう可能性がなくなります。

コメントを投稿

0 コメント