iOS6のキャッシュに気をつけろ(どんな風に?)

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
噂によると世のデベロッパたちにとっては周知の事実らしいことなのですが、その世のデベロッパというカテゴリの中に入っているはずの僕は全く知りませんでした。

iPhone持ってないからな……言い訳ですけど。



AjaxでPOSTするときのお話

iOS6のsafariでページを開いたときの話なんですが、AjaxでデータをPOSTした際、そのPOSTするときのURLをキャッシュしているみたいで、しかもそいつがかなり強力らしく、ページの内容が更新されない現象が起こってしまうようです。

<script>
$('a').click(function(){
  $.ajax({
    data: "POST",
    url: "sample.php",
    success: function(data) {
      alert(data);
    }
  });
});
</script>

//sample.phpの内容
<?php echo '成功' ?>

例えばこんな感じで、リンクをクリックしたらAjaxでデータをPOST送信するようなコードがあるとするじゃないですか。

通信に成功するとsample.phpにデータを送信して、そのページの内容が読み込まれます。だからまあ上の場合だと、POSTしたデータを何するでもなく、alertのところで「成功」っていう内容のダイアログが出てくるだけですけど、iOS6でこの処理をやると、sample.phpの内容がキャッシュされてしまう。

<script>
$('a').click(function(){
  $.ajax({
    data: "POST",
    url: "sample.php",
    success: function(data) {
      alert(data);
    }
  });
});
</script>

//sample.phpの内容
<?php echo '更新されない!?' ?>

だから一度Ajax通信を行った後にsample.phpの内容をちょっと書き換えて再びリンクをクリックしても、内容は変わらない。上記のように文言を書き換えても、alertされるのは相変わらず「成功」の文字。成功してねーよ。

僕は仕事でeラーニング系の学習システムの開発をしているんですが、答案練習のところがまさにAjax通信をしておりまして、この仕様は完全にドストライクでした。

一度不正解の解答をしてしまうと、そのキャッシュが残ってて、次にそのURLに戻ってきて正解を選んでも、表示されるのは相変わらず不正解っていうね。いつまで経っても正解できない、とんだ性悪システムになってしまいました。



URLに適当な文字をつける

じゃあどうやってキャッシュを回避しようかってことなんですけど、単純なのはURLに適当なパラメータをくっつけることです。

<script>
$('a').click(function(){
  var timestamp = new Date().getTime();
  $.ajax({
    data: "POST",
    url: "sample.php?timestamp="+timestamp,
    success: function(data) {
      alert(data);
    }
  });
});
</script>

//sample.phpの内容
<?php echo '更新されたぞ' ?>

キャッシュは全く同じURLに対して効くものですから「sample.php?test=1」と「sample.php?test=2」は違うページとして認識され、キャッシュが効きません。なので、こうやってURLに文字列が被らないようなパラメータをくっつければ、回避できます。

適当にくっつけるとは言っても同じ文字をくっつけては意味がないですから、タイムスタンプみたいに一寸先には違う値が取れるようなものをくっつけるのが良いですね。



まあ~……個人的にはスマートなやり方ではないと勝手に思っているんですがねぇ……。

何て言うか、このパラメータってキャッシュを回避するためだけにくっつけるわけで、実際このパラメータをページ内で何かに使うわけじゃないじゃないですか。

//sample.php?age=20
$age = $_GET['age'];
echo '彼の年齢は'.$age.'歳です'

こんな感じで何かしら使うならともかく、何にも使わないパラメータをURLに入れるのはどうも許せないっていう、よく分からないこだわりを持っているんですね、僕は。何の意味もない、いや意味はあるんだけど、自分で使うわけでもなパラメータをつけるってのは、ポケットにゴミを入れて持ち歩くようなもんだと思ってるわけですよ。

でも実際にゴミだったのは僕のこだわりの方だったってことが今回分かりました。



$.ajaxにはcacheというオプションがあるのだけれど


<script>
$('a').click(function(){
  $.ajax({
    data: "POST",
    url: "sample.php",
    cache: false, //デフォルトはtrue
    success: function(data) {
      alert(data);
    }
  });
});
</script>

こんな感じで、キャッシュを効かせないようにする設定が、$.ajaxにはあるんですね。

あるんですが、でもこれは、GET通信のときにURLの後ろにタイムスタンプをくっつけるようにしてくれるだけらしいです。

よーするに、POST通信時には意味がないってことですね。



僕はずっと、この「cache:false」で何とか対応したいなぁ、URLに意味のない文字くっつけるの嫌だもんなぁって思って悪戦苦闘してたんですが、それは無駄な努力だったってことですね。

それどころか、仮にこれが有効になったとしても、実際やってることはURLの後ろに文字をくっつけてキャッシュを回避しているだけなので、僕のURLの後ろに余計な文字をくっつけたくないとかいうこだわりだかプライドは、限りなく無価値だったってことになりますね。結局くっついてるわけですからね。ちくしょう。

まあ元々僕のプライドなんてフライドポテト2本分くらいの価値しかないから、別に良いんですけどね。ちくしょう。





というわけで、iOSにおけるAjax通信時のキャッシュ回避方法でした。

僕はざっくりとしか説明してないですが、もっと詳しい内容が見たーいって場合は、.Developさんというサイトの記事などを見れば分かると思います。僕もこの記事を書くにあたり、参考にさせていただきました。この場を借りてお礼申し上げます。

あーざーっす!
 もしかしたら何か関連しているかも? 
 質問や感想などお気軽にコメントしてください