XMLHttpRequestの重複リクエストとか

例えばキーボードを打つことがトリガーとなってリクエストが飛ぶ場合(例えば自動で逐次検索するとか)、リクエストが連続して出ることは覚悟せんといかん。その場合の対処としては何が考えられるやろうか。

ひとまず普通に考えられるもの。

  1. 直ちに前のリクエストをabort()して新しいリクエストを飛ばす
  2. タイマを仕掛けて、一定時間後待ってからリクエストを飛ばす(待機中だったらタイマをリセットして書換え)

つまり、greedyにやるかlazyにやるか。*1

1.の場合、abort()をしても直ちにTCPコネクションが切れるわけもなくて、実は結構 後処理に時間がかかる。だからXMLHttpRequestオブジェクトを使いまわし(())にしてたりすると、onreadystatechangeに指定した関数が予期せぬタイミングで実行されたりして嫌な感じになったり。また、その都度新しいオブジェクトを作成していても、下手にabort()すると切断処理に時間を食って、表示も更新されへんで見た感じ固まったように見えたりするかもしれんから、注意が必要かも。
レスポンスが必要な場合、ガシガシ新規オブジェクトを作って、古いのはabort()しないで放っておくのが一番マシな動作をしている気がする。
また、CygwinApacheを使っているから不安定なんかもしれんが、連続してabort()しまくっているとApacheがハングしてくれた。ApacheのTimeout値を小さくしてもやっぱりハングしたんで、タイムアウトがどうこういう問題でもなさげ。一種のDoS攻撃になってるような気がするが、Cygwin版だけの不具合やと思いたいなぁ…。それとも俺のプログラムが腐ってるだけか?<ぉ

2.は試してへんが、実現できれば普通に良さげ。setTimeoutとかを使ってsendすれば良いんやろうか。そのうち試そう…。試してみた。

    clearTimeout(timerID);
    req = createXMLHttpRequest();
    req.onreadystatechange = onReady(req, proc);
    req.open('GET', cgi, true);
    /*req.send('');*/
    timerID = setTimeout('req.send(\'\');', 400);

作ってたプログラムの抜粋。太字にしたあたりを追加した感じ。これだけでかなり反応が改善したような気がする。遅延時間を用途によって調整すれば良いやろう。
ただしこれはreqがグローバル変数やった場合か。まぁ連続リクエストを調整しようと思ってるんやったらこれで十分やとは思うが…。

*1:ああ、あと前のが完了するまで待つとかいうのもあるけど、必要なら並行してリクエストを出したほうがマシ。返ってくる順序はHTTP的に保証されるような気がするし。