第41回学友会総会にて使われた講堂システムの概要
CGI
今回の要である多人数入力・多人数編集によるログ出力CGIだが、これをHTMLの力だけで作ることには大きな壁があった。
まずHTMLでの自動更新だが、ブラウザの機能なのか、放置しすぎると更新しなくなることが判明した。
さらに、更新が数秒間隔で行われると、全ページを読み込み、再描写するだけで画面がちらつき、文字が見難くなってしまった。
これらの問題を解決すべく、HTMLファイルを更新せずにコンテンツを更新させる、AjaxとDOMと呼ばれる技術を使うことにした。この2つの技術はJavaScriptで扱うことができる。
基本的な考え方は、まずHTMLを読み込み、Ajaxの非同期通信でCGIの実行結果を受け取る。その実行結果を、DOMを用いてHTMLのある場所に代入し、コンテンツが更新される。そのためCGIでは、Content-typeがtext/htmlとなるのに対し、出力はHTMLの断片情報のみとなる。(htmlタグなどは必要ない。)
これを数秒間隔で行えば、途切れることなく、画面がちらつくことなく更新することができる。
しかし、これにも問題が発生した。まず、例えば大きな画像を一面に出すと、再描写により画面がちらついてしまうということ。
さらに、IEのキャッシュ機能が強力で、同じアドレスの出力結果を保存してしまうので、一度も画面が更新されない事態が発生した。
そこで、先人の知恵として、アドレスに?をつけると、それ以降がGETデータとして送信されるが、それはIEのキャッシュに新規に追加されていくため、?以降のデータを毎回変更することで、確実にページを更新できるというものがある。
これを実現するために、更新回数を記録するカウンターを用意するという手もあるが、もしHTMLを更新すればカウンターが初期化され、キャッシュにたまっているファイルを読み込んでしまう。これを回避すべく、現在のh時m分s秒を取得し、h*10000+m*100+sという数値を?以降に結合することとした。
これで更新は確実となったが、画面のちらつきが抑えられない。そこで、今度は最少更新をさせる。
Ajaxには同期通信・非同期通信というものがあり、同期通信は普通の関数を実行するのと同様、上から順番に実行され、処理が終わるまで次の処理は実行されない。しかし非同期通信は、通信中は処理を飛ばして次の処理を実行し、通信ステータスが変わるごとに指定した関数を実行する。例えばよく使われるのが、通信終了時にHTMLの内容を更新する処理を実行させる、というものだ。
これらを使い、次のようにして最少画面更新を実現した。まず、編集者がログを更新させると、あらかじめ用意してある別ファイルに、現在時間(今回はPerlのtime()関数で取得した値そのもの)を書き込む。次に、出力用のHTMLの方では数秒間隔でそのファイルに同期通信でアクセスし、内容を今保持している値と比べる。もし値が異なるのであれば非同期通信を開始し、画面を更新するとともに先ほどのデータを変数に保存し、次の同期通信で得られた結果と比較する。
最後に自動更新時の初期値であるが、0を指定すると無理矢理F5で更新したときに一度古い情報が出てきてしまう。そこで、初期値に乱数を入れた。これで更新時に一致することはほぼないだろう。
これにより最小更新が実装され、画面のちらつきも最小限に抑えることが可能になった。