一回しか押していないのに、申し込みが二件届いた。原因は僕のボタンだった

反応がないボタンは、もう一度押される。
押せなくするだけでは足りなかった、二重送信の話。

お問い合わせフォームから、同じ内容の申し込みが二件届いていた。
名前も本文も一字一句同じで、受け取った時刻だけが三秒違う。

いたずらでも手違いでもなかった。
送ってくれた人は、一回しか押していないつもりだった。

反応がないと、人はもう一度押す

送信ボタンを押してから、実際に受け付けが終わるまでには少し時間がかかる。
内容を保存して、通知のメールを送って、完了の画面を出す。
速い回線でも一秒、混んでいれば数秒。

その数秒のあいだ、画面には何も起きない。
ボタンは押す前とまったく同じ顔をして、そこに座っている。

押した人からすれば、これは「押せていない」のと区別がつかない。
だからもう一度押す。
僕だって、他人のサイトで同じことをしている。

つまり二重送信は、押した人の不注意ではない。
待たせているあいだ、こちらが何も言わなかったせいだった。

JavaScriptができるのは、押せなくすること

いちばん手っ取り早い対策は、押された瞬間にボタンを無効にすることだ。
JavaScript でボタンの disabled を true にすると、それ以降のクリックは効かなくなる。

ただ、ここに初心者がよく踏む段差がある。
送信ボタン自体を無効にするタイミングを間違えると、送信そのものが止まってしまうことがある。

ブラウザは、無効になっている入力欄やボタンの値をサーバーへ送らない。
送信の処理が始まる前に無効にしてしまうと、そのボタンの値が抜け落ちる。
ボタンの値で処理を分けている作りだと、これで動かなくなる。

順番としては、送信の処理を先に走らせて、そのあとで無効にする。
フォームの送信イベントの中で無効化する、と覚えておけばだいたい間違えない。

それでも、JavaScript だけでは守りきれない

ここで終わりにしたいところだけれど、これだけでは足りない。

JavaScript は、見ている人の手元のブラウザで動いている。
何かの理由で読み込まれなければ、無効化のしかけごと存在しないことになる。
開発者向けの画面から、無効を解除して押すこともできる。

もっと素朴な経路もある。
送信は届いていたのに、返事が返る前に回線が切れた。
画面には何も出ないから、押した人は最初からやり直す。
このとき、ボタンの無効化はまったく仕事をしていない。

だから受け取る側でも守る。
フォームを表示するときに、その一回ぶんだけ有効な合言葉を紛れ込ませておく。
受け取ったらその合言葉を使い済みにして、同じものが二度目に来たら受け付けない。

もっと簡単に済ませるなら、同じ相手から同じ内容が短い時間のうちに来たら一件として扱う、という線引きでもいい。
完璧ではないけれど、実際に困っていた二重送信はこれでほとんど消えた。

いちばん効いたのは、押したことが見えるようにしたこと

しかけを二つ入れておいて、最後に効いたのは表示のほうだった。

押された瞬間に、ボタンの文字を「送信中」に変える。
色を薄くして、指のかたちのカーソルもやめる。
これだけで、二度押しの報告は目に見えて減った。

技術で止めるのは、起きてしまったことへの後始末だと思う。
起きなくするのは、待っている人に「いま動いています」と伝えることだった。

ボタンを直したというより、黙っていたのをやめただけの話だった。

スタンプラリーに挑戦する 行った場所・気になる場所は、現地チェックインでスタンプに残せます。 みんなのコースを見てみる 会員が作ったスポット巡りのコースを都道府県から探せます。自分だけのコースも作れます。

技術ブログ一覧へ戻る