confirmファンクションの挙動がヤバイ

今回は、ブラウザ上で使うjavascriptについて。

confirmポップアップが進化している

confirmファンクションは、こんな感じでOK/キャンセルを出すポップアップを出すものだ。

f:id:osajiru:20141004080610p:plain

お手軽にユーザーに確認を取れるので、世に出ているインターネットサイトから業務システムまで、色々なところで使用されている。

大体こんな形で書くだろう。

if (confirm('いいじゃないのん?')==false) {
  console.log('ダメよ、ダメダメ。');
} else {
  console.log('ええで!');
}

このconfirmポップアップ、ブラウザ間で挙動に違いがある。
IE/Safariでは、OK/キャンセルのボタンを持つポップアップが出て、入力結果をtrue/falseで返すのみの動作をする。

これだけであれば、何の問題もない。いつものconfirmポップアップだ。

でも、ChromeとFireFoxは、こいつが拡張されている。

例えばChrome。同じconfirmポップアップを連続して出し、キャンセルで閉じ続けると
下記のような “このページこれ以上ダイアログボックスを生成しない” チェックボックスが出る。

f:id:osajiru:20141004080641p:plain

FireFoxも同じように、
“このページによる追加ダイアログ表示を抑止する"チェックボックスが出る。

f:id:osajiru:20141004080712p:plain

挙動が違う!

下記の操作をしてみよう。

  1. confirmポップアップを繰り返して表示し、チェックボックスを出す。
  2. こいつをチェックして、キャンセルを押す。
  3. もう一回このポップアップを出す。

チェックをしたんで、当然ポップアップは出ない。
でも、この時、どういう風に処理が流れているかというと・・・

Chrome

Chromeは、キャンセルされた扱いになる。
confirmファンクションは、ポップアップを表示せずに、
自動的にfalseを返す
挙動となる。

FireFox

一方FireFox。 confirmファンクションは、ポップアップ表示しないどころか、
例外を返す!!
挙動となる。

例外を返すということは、ちゃんとtry catchを入れていないと、後続処理が行われないということだ。

ヤバイ例

以下、極端な例・・・

ボクは、おさじるネットバンクという銀行サイトを作った。
この銀行は、男らしさを売りにしている。

このサイトも、[3億円振込]ボタン以外何もない、とても男らしい作りだ。
しかも、一応顧客に確認ポップアップを出すという親切設計。

この処理は、こう実装した。

function 3億円振込ボタン押下() {
  口座引き落とし処理();
  if (confirm('振り込んじゃうよ?いいの?')==false) {
      口座戻し処理();
      return;
  }
  相手先口座入金処理();
}

トランザクションを分けてデータ更新をすることはまずやらない。 でも一応例ということで・・・・ (でも、データではなく、画面入力制御の整合性という意味なら充分ありえますヨ。)

さて、これをChromeで動かしてみよう。

キャンセル、キャンセル、抑止、キャンセル・・・・
これで自動キャンセルする動作になり、振り込めなくなった。

これはこれでよいだろう。

一方、FireFox。

キャンセル、キャンセル、抑止、キャンセル・・・・

あ!ボタンを押す度に3億円減っていく!
相手先にも振り込まれてない!
confirmファンクションで例外が発生し、口座戻し処理も相手先口座入金処理も飛ばされてしまったのだ。

消えた3億円。
平成の3億円事件発生の瞬間だ。

3億円といえば、ボクの大好きなよなよなエールを100万本買える金額だ。

つまり

つまり、
confirmファンクションの後で、データや表示の整合性を取る必要が有る場合、confirmファンクションは、try catchで囲まないとダメ。
ということ。

上のクソコードでいうと

function 3億円振込ボタン押下() {
  口座引き落とし処理();
  try {
    if (confirm('振り込んじゃうよ?いいの?')==false) {
        口座戻し処理();
        return;
    }
    相手先口座入金処理();
  } catch (e) {
    口座戻し処理();
  }
}

とか。

© 2009-2017 Osajiru All Rights Reserved.