JavaScriptのデータ通信, form, fetchとFormData
JavaScriptでデータ通信する時に最近考えることが多いのでメモしておこうかなと思います.
formにデータを突っ込んでsubmitする
form
を取り出してsubmit
メソッドを呼び出す方法.
form
に既に入っている情報で足りない時はinput
要素をform
に足してやります.
const element = document.createElement("input");
element.name = name;
element.value = value;
form.appendChild(element);
もともとフレームワークがform
にCSRF対策のtokenとか入れてると面倒が少ない.
formベースで作っておくとJavaScript使わない方式にも変えやすい.
formの送信先がredirect先を指定している場合に自動でリダイレクトしてくれる.
送信後のページの再読み込みが自動で行われる.
FormDataを生成してfetchする
ページを最読み込みさせてはいけない場合(入力中の<textarea>
の内容を保持したままにしたいとか)はform
をsubmit
してはいけないのでfetch
などを使う.
その際FormData
を使うと便利.
FormData - Web API インターフェイス | MDN
new FormData(form)
のようにformをFormDataに突っ込んであげるとそれに合ったFormData
を生成してくれる.
ユーザにForm上で入力してもらってデータを生成出来るのも良いし,
フレームワークがform
に埋め込んだtokenとかも送信してくれるのでYesodとか使ってても特別なことをしなくていい.
認証した状態で通信したい場合はcredentials: "same-origin"
を追加しましょう.(よく忘れる)
fetch(form.action, {
method: "post",
headers: { "accept": "application/json" },
body: new FormData(form),
credentials: "same-origin"
}).then(response => {
if (response.ok) {
form.reset();
}
else {
throw response;
}
}).catch(err => {
form.reset();
alert(err);
throw err;
});
エラーキャッチをrespose.ok
とcatch
両方でやらないといけないのが面倒くさい.
何故こんな仕様になったんだろう.
ユーザが入力した情報で足りない時にはFormData
のappend(name, value)
メソッドを使います.
fetchのpolyfill
IEはfetchに対応していない.(575) Can I use... Support tables for HTML5, CSS3, etc
なのでIE対応させたい場合は以下の2つのpolyfillを追加しておきましょう. どちらもcdnjs.com - The best FOSS CDN for web related libraries to speed up your websites!で読み込めます.
- stefanpenner/es6-promise: A polyfill for ES6-style Promises
- github/fetch: A window.fetch JavaScript polyfill.
本当に動くかどうかはIE使ってないので知りません.
XMLHttpRequest
現在のfetch
はアップロード状態を取得できないため,
アップロード時にプログレスバーを表示したい場合などはサーバサイドにAPIを追加するか,
XMLHttpRequest
を使うしかない.多分.
幸いにもまだそんな案件にはぶち当たっていません.(仕様を捻じ曲げて回避)