本連載は、ASP.NET AJAXのクライアントサイド・フレームワークであるMicrosoft AJAX Library(以降、MS AJAX Lib)の主要な機能について詳解するものだ。本連載ではASP.NET AJAX 1.0(ASP.NET 2.0)環境を前提に解説を進めているが、先般リリースされた.NET Framework 3.5(のASP.NET 3.5)でもASP.NET AJAXの基本的な機能はさほど変わっていない。基本的には、ASP.NET AJAX 1.0で習得した知識は、ASP.NET 3.5でもそのまま使えると考えていただいて差し支えないだろう(ASP.NET 3.5でのASP.NET AJAXの変更点については、別稿「特集:ASP.NETアプリ開発者のためのVisual Studio 2008新機能」を参照いただきたい)。
さて、ここまで本連載では、MS AJAX Libによるオブジェクト指向プログラミングに始まり、UpdatePanelコントロールとの連携、Ajax対応サーバ・コントロールの構築までを紹介してきた。最終回となる今回は、これまで扱うことのできなかった小粒な――しかし、重要な機能であるSys.StringBuilder、Sys.Debug、Sys.Net.WebRequestオブジェクトなどの機能について紹介していく。
文字列連結を効率的に行うには? − Sys.StringBuilderオブジェクト −
Ajaxプログラミングを行ううえでは、文字列連結を繰り返し行うケースが意外と少なくない。例えば、サーバサイドから構造化データを受け取って、その内容をリストなどに整形する場合だ(別稿「.NET TIPS:[ASP.NET AJAX]Webサービス・ブリッジ機能により構造化データを受け渡しするには?(基本編)」のようなケースを想定してみるとよいだろう)。
このようなケースでは、もちろんDOMを利用してコンテンツを組み立てても構わない。しかし、コンテンツの構造がそれほど複雑でない場合にはかえってコードが複雑になることから、文字列としてコンテンツを組み立ててしまうことも多い。
そして、JavaScriptで文字列連結を行うのは「+演算子」の役割であるが、繰り返し文字列の連結を行う場合、+演算子を利用するのは好ましくない。というのも、+演算子は逐一文字列の連結を行うため、処理効率がよくないのである。
そこで登場するのが、Sys.StringBuilderオブジェクトだ。Sys.StringBuilderオブジェクトで利用可能なメソッドは以下のとおり。
メソッド |
概要 |
StringBuilder([init]) |
コンストラクタ(引数initは初期値テキスト) |
append(str) |
末尾に文字列を追加 |
appendLine([str]) |
末尾に文字列を追加(改行文字付き) |
clear() |
StringBuilderオブジェクトの内容をクリア |
isEmpty() |
StringBuilderオブジェクトの内容が空であるか |
toString([sep]) |
オブジェクトの内容を文字列に変換(引数sepは区切り文字) |
|
表1 Sys.StringBuilderオブジェクトの主なメソッド |
|
Sys.StringBuilderオブジェクトでは、内部的には連結対象の文字列を配列要素として格納している。そして、最終的にtoStringメソッドをコールしたタイミングで一括して連結処理を行うため、連続した文字列連結に際しては大幅な処理効率の改善を望めるのだ。
具体的にどの程度の効率化になるのか、簡単なコードで確認してみよう。
var begin = new Date(); // 開始時刻
var str = '';
for (var i = 0; i < 50000; i++) {
str += 'ASP.NET';
}
var end = new Date(); // 終了時刻
$get('result').innerHTML =
begin.toLocaleTimeString() + '<br />' + end.toLocaleTimeString();
|
|
リスト1 文字列を+演算子で連結するコード |
var begin = new Date(); // 開始時刻
var str = new Sys.StringBuilder();
for (var i = 0; i < 50000; i++) {
str.append('ASP.NET');
}
var result = str.toString();
var end = new Date(); // 終了時刻
$get('result').innerHTML =
begin.toLocaleTimeString() + '<br />' + end.toLocaleTimeString();
|
|
リスト2 文字列をSys.StringBuilderオブジェクトで連結するコード |
それぞれ文字列連結を+演算子とSys.StringBuilderオブジェクトで5万回繰り返した場合の処理時間を計測するものだ。筆者の環境では、前者が40秒かかっているのに対して、後者は3秒で処理が終了している。
もちろん、実際のアプリケーションで5万回もの文字列連結を行うことはあまりないかもしれないが、連続した文字列連結を行う場合には、Sys.StringBuilderオブジェクトを利用するのが好ましいことはお分かりいただけるだろう。
オブジェクトの内容を確認するには? − Sys.Debugオブジェクト −
デバッグは、JavaScriptプログラミングを行うに際して最も悩ましい問題の1つだ。最新の統合開発環境であるVisual Studio 2008ではJavaScriptサポートが大幅に強化され、デバッギングも効率化されているが(別稿「ASP.NETアプリ開発者のためのVisual Studio 2008新機能」を参照)、まだまだVisual Studio 2005ベース、あるいは、そもそもクライアントサイド開発はテキスト・エディタで開発を行っているという読者も多いはずである。このような環境では、実行途中の変数を確認するのもなかなか至難である。いまだに、コードの途中にalert関数やinnerHTMLプロパティを埋め込んで、変数を出力している方も少なくないのではないだろうか。
しかし、(当然のことながら)このような方法は好ましいことではない。というのも、リリースに当たっては、これらのデバッグ用命令はすべてコメントアウト(削除)する必要があるし、後々のコード修正では、コメントアウトしたデバッグ命令をまたコメントインしなければならないかもしれない。これはコードが大規模になれば、なかなかに手間な作業であるし、そもそもコメントアウトの漏れにより本番環境で不必要な情報が出力されてしまった、というような不具合の原因にもなるものだ。
そこで登場するのが、Sys.Debugオブジェクトなのである。Sys.Debugオブジェクトは、実行途中の変数を出力するための簡易な手段を備えたオブジェクトだ。Sys.Debugオブジェクトで利用可能な主なメソッドは、以下のとおり。
メソッド |
概要 |
assert(condition [,msg [,flag]]) |
条件conditionがfalseである場合にはメッセージ表示のうえ、デバッガを中断(引数flagは呼び出し元の関数名を表示するかどうか) |
fail(msg) |
出力ウィンドウにメッセージ表示のうえ、デバッガを中断 |
trace(msg) |
トレース・コンソールにテキストを出力 |
traceDump(obj [,name]) |
トレース・コンソールにオブジェクトの内容をダンプ(引数nameはオブジェクトの名前) |
clearTrace() |
トレース・コンソール上のメッセージをクリア |
|
表2 Sys.Debugオブジェクトの主なメソッド(すべて静的メソッド) |
|
この中でもtraceDumpメソッドはなかなか有用なメソッドであるので、要注目だ。まずは、具体的なコードを見てみよう。
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<textarea id="TraceConsole" cols="50" rows="8"></textarea>
<script type="text/javascript">
<!--
var obj = {
'title' : 'ASP.NET AJAXプログラミング',
'publish' : 'マイコミ',
'price' : 3600
}
Sys.Debug.traceDump(obj, '[obj]');
//-->
</script>
|
|
リスト3 traceDumpメソッドを使ったJavaScriptのコード(traceDump.aspx) |
このページの実行画面は次のようになる。

|
図1 オブジェクト・リテラルの内容が可読形式で表示される |
|
traceDumpメソッドは、指定された変数の内容を「id="TraceConsole"」*1と指定されたテキストエリアに出力する。traceDumpメソッドのうれしい点は、変数が配列やオブジェクトである場合にも、その要素やプロパティ情報までをきちんと表示してくれる点だ。これによって、(例えば)非同期通信で構造データを取得した場合なども、その内容を簡単に確認することができる。
*1 id値は大文字/小文字を厳密に区別するので、要注意。
|
また、すべてのtraceXXXXXメソッドには、「id="TraceConsole"」であるテキストエリアをページから削除するだけで出力をオフにできるというメリットもある。そして、その動作のオーバーヘッドが限りなくゼロになるという点にも注目だ。
試しに、以下のようなコードを見てみよう。
<textarea id="TraceConsole"></textarea>
<div id="result"></div>
<script type="text/javascript">
<!--
var begin = new Date();
for (var i = 0; i < 1000; i++) {
Sys.Debug.traceDump('TEST', '[INFO]');
}
var end = new Date();
$get('result').innerHTML
= begin.toLocaleTimeString() + '<br />' + end.toLocaleTimeString()
//-->
</script>
|
|
リスト4 traceDumpメソッドでトレース・メッセージを繰り返した例 |
このコードは、traceDumpメソッドで1000回、トレース・メッセージを表示したときの実行時間を計測するものだ。このコードを<textarea>タグをそのままにした状態、コメントアウトした状態で、それぞれ実行してみよう。筆者の環境では前者でおおよそ10秒ほどかかっている処理が、後者ではほぼゼロになっていることが確認できた。