XMLHttpRequestの競合を起こしてしまっていた
こんなアホな事をする人が他にいるとは思わないけれど、あまりに自分に腹がたったのでメモ。
XMLHttpRequestを同時に複数行いたいときは、接続の数だけXMLHttpRequestをnewする必要がある。
//XXX これはバグコード var request = new XMLHTTPRequest(); path1 = 'ごにょ'; path2 = 'ごにょごにょ'; request.open('GET', path1, true); request.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { //ごにょ } }; request.send(null); request.open('GET', path2, true); request.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { //ごにょごにょ } }; request.send(null);
みたいなことはできない。これをやると通信の結果が上書きされたりして、バグがでる。
しかも、タイミング次第でいろいろな現象になるので、再現性の低い(知らない人にとっては)分かりにくいバグになる。
new XMLHTTPRequest();で作られるのは、接続してくれるエージェント(ブラウザ)ではなくて、接続の経路だということを覚えておこう。
したがって、上記の場合は
var request1 = new XMLHTTPRequest(); var request2 = new XMLHTTPRequest(); //以下略
としないといけない。
ただ、これは面倒なので
function simple_GET(path, callback){ var xmlhttp = new XMLHttpRequest(); xmlhttp.open('GET', path, true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { callback(xmlhttp.responseText;); } }; xmlhttp.send(null); }
みたいなラッパーを作っておくと、simple_GET関数を呼ぶたびにローカル変数として、別の変数xmlhttpが作られるので楽になる。
ここまでは別に珍しくもない話。
ただ、今回俺はvar xmlhttpのvarを付け忘れて、xmlhttp = new XMLHttpRequest();としてしまっていた。
言うまでもなく、関数内でvarを付けないで変数を使うとグローバル変数として扱われるので、結局最初に紹介したバグケースと同じことをやってしまっていた。
なにしてるんだ俺...orz