Web プログラミング演習 STEP9 Ajax を利用した RSS フィードのタイムライン表示
Ajax Asynchronous JavaScript + XML クライアントサイド ( ブラウザ内 ) で非同期サーバ通信と動的ページ生成を組み合わせる技術の総称 ウェブアプリケーションの操作性向上 ( ページ遷移を伴わない ) サーバとの小刻みな通信 = 必要なデータを必要な時に要求 ( リクエスト ) 非同期通信 = サーバの応答 ( レスポンス ) を待つ間も処理を実行可能
同期通信と非同期通信 (1) ブラウザ http サーバ ブラウザ http サーバ リクエスト リクエスト 応答待ち レスポンス 割り込み レスポンス レスポンス処理は割り込み ( コールバック関数 ) を利用 同期通信 非同期通信
同期通信と非同期通信 (2) ブラウザ http サーバ ブラウザ http サーバ リクエスト 1 リクエスト 1 レスポンス1 リクエスト2 レスポンス2 リクエスト 2 レスポンス 2 レスポンス 1 リクエストの順序とレスポンスの順序が一致しないことがある 同期通信 非同期通信
マッシュアップと Ajax マッシュアップ (mashup) 複数のウェブサービスを組み合わせて, ひとつの複合サービスを実現すること ( 音楽用語から派生 ) 複数の異なる音源を組み合わせて一つの曲に仕上げる 組み合わせを前提としたウェブサービス API の提供 Google Maps, Amazon 商品検索, 楽天トラベル API,. 他多数 クライアントサイドマッシュアップ ブラウザから JavaScript や iframe を使って API を利用 比較的時間のかかるサービスを利用する場合は,( 応答待ちをしない )Ajax が適切 サーバサイドマッシュアップ
XMLHttpRequest 非同期 Http 通信を実現する機能を提供する,JavaScript 組込みクラス 主要メソッド open(http メソッド, URL, 非同期フラグ, 名前, パスワード ) サーバとの通信方式を設定 HTTP メソッド : GET, POST など URL:HTTP アクセスする先注 : 表示ページと同一サーバ上の URL にしかアクセスできない 非同期フラグ :true なら非同期通信を行う ( 省略時は true) 名前, パスワード : ユーザ認証が必要な場合に指定 ( 省略可 ) send( 送信データ ) サーバへのリクエスト送信 送信データ :POST する場合に送るデータ ( 不要の時は )
XMLHttpRequest( つづき ) 主要プロパティ onreadystatechange 通信状態 (readystate) の変化時に呼び出される関数 readystate 通信状態 responsexml 0 (uninitialized: 読み込み開始前の初期状態 ), 1 (loading: 読み込み中 ),2 (loaded: 読み込んだ ), 3 (interactive: 読み込んだデータを解析中 ) 4 (complete: 読み込んだデータの解析完了 ) レスポンスを XML DOM 形式で取得
典型的な Ajax プログラミング // リクエストの送信 function ajaxrequest(url){ var req = new XMLHttpRequest(); req.open('get', url, true); req.onreadystatechange = function(){ if(req.readystate==4){ onresponse(req); req.send(''); // コールバック関数 function onresponse(req){ var myxml = req.responsexml;... レスポンス XML の処理... XMLHttpRequest オブジェクトの生成通信方式の設定イベント処理関数の設定通信状態が 4( 解析完了 ) になったらコールバック関数を呼び出す リクエスト送信 XML DOM 形式で取得
Ajax で RSS フィードを処理する RSS フィード サイトで公開されている情報の要約を XML 書式で記述したもの この演習では RDF Site Summary(RSS0.9, RSS1.0) を利用 Ajax でフィード処理 興味のあるサイトの RSS フィードをリクエスト コールバック関数でフィードの中身を調べて, 表示用 HTML タグを生成してページに埋め込む
演習 % cd myblog 次ページに示す JavaScript を記述したファイルを作成 ファイル名は feed.js タイムライン表示用の HTML ファイルを作成し, JavaScript を利用 ファイル名は timeline.html クライアントサイドマッシュアップなのでページ記述は静的
feed.js //RSS フィードの読込指示 function insertfeed(){ ajaxrequest('/~manda/webprg/rss.php'); // リクエストの送信 function ajaxrequest(url){ var req = requestobj(); リクエストする rss フィードの URL を引数として ajaxrequest 関数を呼び出す req.open('get', url, true); req.onreadystatechange = function(){ if(req.readystate==4){ onresponse(req); req.send(''); // 通信オブジェクトの生成 function requestobj(){ return new XMLHttpRequest(); ( 次ページへつづく )
feed.js( つづき ) // コールバック関数 function onresponse(req){ var rss = req.responsexml; if(rss){ var channel = rss.getelementsbytagname('channel')[0]; var title = channel.getelementsbytagname('title')[0].firstchild.nodevalue; サイトタイトル var link = channel.getattribute('rdf:about'); サイトURL var items = rss.getelementsbytagname('item'); for(var i = 0; i < items.length; i++){ エントリごとの繰り返しエントリタイトル var ititle = items[i].getelementsbytagname('title')[0].firstchild.nodevalue; エントリ日付 var idate = items[i].getelementsbytagname('date')[0].firstchild.nodevalue; エントリ本文 var ibody = items[i].getelementsbytagname('description')[0].firstchild.nodevalue; エントリURL var ilink = items[i].getattribute('rdf:about'); showtimeline(title, link, ititle, idate, ibody, ilink); エントリをタイムラインに挿入 ( 次ページへつづく )
feed.js( つづき ) // タイムラインへの挿入 function showtimeline(title, link, ititle, idate, ibody, ilink){ var entry = document.createelement('div'); entry.setattribute('class', 'entry'); entry.innerhtml = ' <h3 class="date">'+idate+'</h3> <h4><a href="'+link+'">'+title+'</a><br/> <a href="'+ilink+'">'+ititle+'</a></h4> <div class="body">'+ibody+'</div> '; var tline = document.getelementbyid('timeline'); <div class= entry > 要素を作成 エントリごとの HTML 記述 ( 各自の仕様にあわせる ) ヒアドキュメント風の書き方だが実際は単なる文字列の代入 (JavaScript にヒアドキュメントは無い. 行末の は次行への継続を意味する ) タイムライン (id= timeline の要素 ) を取得 var entries = tline.getelementsbyclassname('entry'); タイムラインに挿入済みのエントリ for(var i = 0; i < entries.length; i++){ (class= entry の要素 ) に対する繰り返し var edate = entries[i].getelementsbyclassname('date')[0].firstchild.nodevalue; if(edate < idate) break; 日時 (class= date の要素の内容 ) を取得 挿入するエントリよりも旧ければ繰り返しを抜ける if(i < entries.length){ tline.insertbefore(entry, entries[i]); 途中で抜けた場所に挿入 else{ tline.appendchild(entry); 末尾に追加 ( ソースプログラム )
コールバック関数 (onresponse) の処理内容 各エントリーの HTML 記述を作成し,"timeline" という id 属性を持つ HTML 要素の中に日時順に挿入する <div class="entry"> <h3> 日時 </h3> <h4> <a href=" サイト URL"> サイトタイトル </a><br/> <a href=" 個別エントリ URL"> 個別エントリタイトル </a> </h4> <div class="body"> 本文 </div> </div> 挿入 <div id="timeline"> </div>
timeline.html の作成 head 領域内で feed.js を読み込む <head>... <script type="text/javascript" src="feed.js">//</script>... </head> body タグの onload 属性で insertfeed 関数を実行 <body onload="insertfeed()"> body 領域内にタイムライン表示用の HTML 要素を置く... <div id="timeline/>...
タイムライン表示の確認 timeline.html にアクセスして, ウェブプログラミング演習サイトのエントリが表示されれば OK 他サイトのフィードを追加 insertfeed 関数の中で,ajaxRequest 関数を複数個呼び出す 引数は自分や友達のブログの RSS フィードの URL /~ ユーザ ID/myblog/rss.php リクエスト順序と表示順序が異なるときがある (= 非同期通信 )
次回の予定 JavaScript を利用した入力チェック