Ajaxでチャット&Ajax:JSON簡易フレームワーク
PerlのリハビリとJavaScriptの勉強がてら、定番のAjaxを用いたチャットを作ってみました。
JavaScriptのほうでは、prototype.jsを使ってみました。
サーバ側はともかく、クライアント側はなかなか難しくて試行錯誤の連続でしたが一応は完成しました。
大した物じゃないんですが、やっぱり画面遷移なしでチャットができちゃうというのは感動します。
発言→サーバ側CGIがログに書き込む、定期的にログを直接読み込んで表示という流れなんですが、ログを読みに行く間隔がなかなか難しい。
LAN内ですと0.5秒設定とかでかなり良い動きをするんですが、インターネット経由となるとどうなるのかなぁと思ったり。
本当はログを丸ごと読んだりせず、必要な分だけ読み込む、等の措置も必要なのかもしれません。
サーバとブラウザの通信にはすべてJSONを使うことにして、簡単なフレームワーク(?)みたいな物を作りました。
# LLALD.pm package LLALD; use strict; use JSON::Syck; sub new{ my $class = shift; my $self = bless({ req => {}, res => {}, }, $class); $self->_init; return $self; } sub _init{ my $self = shift; my $query; if( $ENV{REQUEST_METHOD} eq 'POST' ){ read( STDIN, $query, $ENV{CONTENT_LENGTH} ); } else { $query = $ENV{QUERY_STRING}; } $self->{req} = JSON::Syck::Load( $query ); } sub forward_to{ my $self = shift; my $controler = shift; my $runmode = shift; $runmode = $self->{req}->{_runmode} || 'default' if( !$runmode ); $controler->$runmode( $self ); } sub request{ my $self = shift; return $self->{req}; } sub response{ my $self = shift; return $self->{res}; } sub put_results{ my $self = shift; print "Content-type: text/plain\n\n", $self->results; } sub results{ my $self = shift; return '(' . JSON::Syck::Dump( $self->{res} ) . ')'; } 1;
これだけでもある程度想像はつくと思うのですが、本体のCGIはこんな感じです。
# chat.cgi #! /usr/bin/perl use strict; use LLALD; use Controler; my $d = new LLALD(); $d->forward_to( 'Controler' ); $d->put_results;
そして、Controlerは
# Controler.pm package Controler; use Model; use strict; sub default{ my $c = shift; my $j = shift; } sub newMessage{ my $c = shift; my $j = shift; if( !$j->request->{name} or !$j->request->{message} ){ return; } Model::unshiftAMessage( name => $j->request->{name}, message => $j->request->{message} ); } 1;
そしてブラウザ側。json.jsを使用します。
function sendRequest( url, obj, complete ){ new Ajax.Request( url, { asynchronous : 1, method : 'post', postBody : obj.toJSONString(), onComplete : function(request){ complete( eval(request.responseText) ); } } ); }
要するに、ブラウザ側からJSON形式でデータをPOSTし$j->responseに格納、そのデータによって処理を振り分けControler内でうじゃうじゃし、$j->responseにデータをぶち込んで、LLALD.pmがそのデータをJSON形式に変換してブラウザに返す。
(今回はサーバ側からとくにデータを返していませんが。)
ブラウザはJSON形式のデータをObjectに戻して、いろんな処理をする。