SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Cloud SQLで学ぶ業務・基幹系アプリ再入門

HTML5のWeb Workersを追加してさらに高速仕訳入力

Cloud SQLで学ぶ業務・基幹系アプリ再入門(3)

  • X ポスト
  • このエントリーをはてなブックマークに追加

Cloud SQLとWeb Storageを使用した仕訳データ登録サンプル

 ここまで見てきたようにWeb Workersの適用は決して難しくはありません。ここから第3回のサンプルに入っていきますが、今回はWeb Workersの機能を第2回で見てきた仕訳情報登録のサンプルに追加します。その目的はデータ登録時の待ち時間を実質ゼロにし、前回のWeb Storageと合せて仕訳データ登録処理全体での待ち時間の発生を実質ゼロにすることです。

仕訳データの入力とDB登録

(1)仕訳データの画面と処理手順

図6 仕訳データ登録の初期表示画面
図6 仕訳データ登録の初期表示画面

 今回のサンプルは前回のサンプルにWeb Workersを追加した内容になっています。仕訳データ登録の初期表示画面ではWeb Workersを使用できるブラウザかの確認メッセージが表示されます(図6)。

図7 Web storageを使用した貸方コードから勘定科目の検索表示
図7 Web storageを使用した貸方コードから勘定科目の検索表示

 勘定コードを入力するとWeb Storageの検索から勘定科目名が自動表示されますが、借方の勘定科目名は1ms(0.001秒)で表示され、貸方の勘定科目名は0msつまり1ミリ秒以下で表示されています(図7)。その後貸方金額を入力した後、Altキーを押すことによって登録データが非同期でサーバに送信されます。今回のサンプルではサーバ送信はWeb Workersを使用してバックグラウンドで行われているため、クラウドサーバでのデータ登録処理完了までの待ちは発生せず、図8の画面に移行します。

図8 Web Workersでのコンカレントなサーバ送信処理と新規仕訳データ入力
図8 Web Workersでのコンカレントなサーバ送信処理と新規仕訳データ入力

 Altキーの押下と同時に画面の入力データはクリアされ、伝票番号が1インクリメントされて自動表示され、そのまま次の仕訳データ入力を継続することができます。図8では借方コードの入力の途中でバックグラウンドのWeb Workersから実行された仕訳データの登録処理が完了し、そのメッセージが表示されています。

 このように、前回のWeb Storageと今回のWeb Workersを組み合わせることによって、データ入力項目も最小限に抑えながら、実質待ち時間がまったくない仕訳データ登録画面にすることができます。また、万一クラウドでのDB登録でエラーは発生した場合にはアラート画面でエラー内容が表示され、処理が強制的に中断されるようになっています。

 もしWeb Workersでのバックグラウンド処理を使用しなかった場合は、クラウドサーバへのデータ送信から、ビーンズ内でのCloud SQLによるデータ登録が行われ、その結果(ステータス)がブラウザに届くまでは入力処理が中断されることになります。前回の図9ではDB送信・登録処理は0.5秒弱でしたので、この間だけ待てば良いことになりますが、しかしこれはユーザ1人での実行結果で、実際に業務で使用する場合はもっとアクセス数が増え、またネットワークの状態によっては待ち時間はもっと長くなることは当然ありえることで、そのような場合でもWeb Workersを使用すれば待ち時間のないデータエントリを継続できます。

(2)クライアントコード

リスト5 クライアントHTMLとJavaScript(addJournal3.htm)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Google Cloud SQL Journal Entry</title>
<style><!-- .num {text-align: right; }  --></style>
<script type="text/javascript" src="../jslib/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
$(function(){
  if (localStorage){
    $("#stat").text("このブラウザはローカルストレージを使用できます。");
  }else{
    alert("このブラウザはローカルストレージを使用できません。");
  }
  if (window.Worker){
    $("#stat").text("このブラウザはWeb Workersを使用できます。");
  } else {
    alert("このブラウザはWeb Workersを使用できません。");
  }
  var date = new Date();
  var stime = 0;
  var etime = 0;
  $("#check_date").val(date.getFullYear()+"-"+(date.getMonth() + 1)+"-"+date.getDate());
  var jworker = new Worker("jworker.js");  // (1)ワーカオブジェクト生成
  jworker.onmessage = function(e) {        // (2)ワーカから結果を受け取る
    var jwk = $.parseJSON(e.data);
    if(jwk.stat.substr(0,3) == "NO:"){
      alert("登録エラー: "+jwk.stat);      // (3)
    }else{
      $("#stat").text(jwk.stat);
    }
  };
  $("#items").keyup(function(e){
    var eid = e.target.id;
    var dc = eid.split("_")[0];
    var con = eid.split("_")[1];
    if(con=="code"){
      var dc_code = $("#"+dc+"_code").val();
      if(dc_code.length != 6) return;
      stime = etime = 0;
      var storage = $("input[name='storage']:checked").val();
      if (storage=="local"){
        stime = new Date();
        var val1 = localStorage.getItem(dc_code);
        $("#"+dc+"_acct").val(val1);
        etime = new Date();
        $("#stat").text((etime - stime)+"ms");
        $("#"+dc+"_amt").focus();
      } else if(storage=="cloud"){
        stime = new Date();
        var query = {};
        query["mode"] = "get_acct";
        query["acct_code"] = dc_code;
        $.get("/acctsvlt", query, function(res){
          var r = $.parseJSON(res);
          if(r.stat.substr(0,2) == "NO"){
            $("#stat").text(r.stat.substr(3));
          }else{
            $("#"+dc+"_acct").val(r.acct_name);
            etime = new Date();
            $("#stat").text((etime-stime)+"ms");
            $("#"+dc+"_amt").focus();
          }
        });
      }
    }else if ((eid=="credit_amt" || eid=="remark") && e.keyCode==18){
      stime = new Date();
      var query = "mode=addJournal";
      query += "&check_no="+$("#check_no").val();
      query += "&debit_code="+$("#debit_code").val();
      query += "&debit_acct="+$("#debit_acct").val();
      query += "&debit_amt="+$("#debit_amt").val();
      query += "&credit_code="+$("#credit_code").val();
      query += "&credit_acct="+$("#credit_acct").val();
      query += "&credit_amt="+$("#credit_amt").val();
      query += "&remark="+$("#remark").val();
      jworker.postMessage(query);
      // (4)Web WorkersにCloud SQL登録用仕訳データの送信依頼
      $.each(["debit_code","debit_acct","debit_amt","credit_code","credit_acct","credit_amt","remark", "debit_total", "credit_total"], function(){
        $("#"+this).val("");
      });  // (5)画面表示データクリア
      $("#check_no").val(parseInt($("#check_no").val())+1);  //伝票番号のインクリメント
      $("#debit_code").focus();
    } else if (con=="amt"){
      var dc_amt = $("#"+dc+"_amt").val();
      $("#"+dc+"_total").val(dc_amt);
    }
  });
  $("#check_no").keyup(function(){
    if($("#check_no").val().length != 5) return;
    $("#debit_code").focus();
  });
});
</script>
</head>
<body>
<h4>Google Cloud SQL 仕訳データ登録&nbsp;&nbsp;&nbsp;
<span>
  勘定科目参照
  <input type="radio" name="storage" value="local" checked/>ローカルストレージ
  <input type="radio" name="storage" value="cloud"/>クラウドストレージ
</span>
</h4>
<table width="280" border="0" cellspacing="2" cellpadding="0">
  <tr bgcolor="#ccffcc">
    <th align="center">伝票番号</th>
    <th align="center">日付</th>
    <th align="center">会計区分</th>
  </tr>
  <tr>
    <td ><input type="text" size="10" id="check_no" /></td>
    <td ><input type="text" size="10" id="check_date" /></td>
    <td ><input type="text" size="25" value="収益事業等会計" /></td>
  </tr>
</table>
<table width="700" border="0" cellspacing="2" cellpadding="0">
  <tr bgcolor="#ccffcc">
    <th>借方コード</th>
    <th>勘定科目名</th>
    <th>借方金額</th>
    <th>貸方コード</th>
    <th>勘定科目名</th>
    <th>貸方金額</th>
    <th>摘要</th>
  </tr>
  <tr id="items">
    <td><input id="debit_code" type="text" size="7" /></td>
    <td><input id="debit_acct" type="text" size="11" /></td>
    <td><input id="debit_amt" type="text" size="9" class="num" /></td>
    <td><input id="credit_code" type="text" size="7" /></td>
    <td><input id="credit_acct" type="text" size="11" /></td>
    <td><input id="credit_amt" type="text" size="9" class="num" /></td>
    <td><input id="remark" type="text" size="15" /></td>
  </tr>
</table>
<table width="700" border="0" cellspacing="2" cellpadding="0">
  <tr>
    <td width="500" id="stat"><td>
    <th width="100" align="center" bgcolor="#ccffcc">借方合計</th>
    <td width="100"><input type="text" id="debit_total" size="14" /></td>
  </tr>
  <tr>
    <td><td>
    <th align="center" bgcolor="#ccffcc">貸方合計</th>
    <td><input type="text" id="credit_total" size="14" /></td>
  </tr>
</table>
</body>
</html>

 クライアント側のHTMLとJavaScriptは、前回のコードにWeb Workersでの処理を追加した内容になっています。Web Workersを使用した基本的な処理手順については前に簡単なサンプルを紹介しているので問題はないと思いますが、仕訳データ登録に適用した場合の流れを簡単に見ていきます。

 リスト5では(1)でワーカオブジェクトを生成し、その後(2)でワーカから結果を受け取った時の処理を記述しています。処理ではクラウド側のDB登録処理でエラーが発生した場合のみアラートを表示するようにしていますが(3)、正常登録時にステータス表示することももちろんありえるでしょう。ここではワーカへの処理依頼を行う記述の前に、ワーカからの受信処理を記述していますが、もちろん問題ありません。

リスト6 ワーカスクリプト(jworker.js)
onmessage = function(e) {
  var xhr = new XMLHttpRequest();        //(1)
  xhr.open("post", "/acctsvlt", false);  //(2)
  xhr.setRequestHeader("If-Modified-Since", "01 Jan 2000 00:00:00 GMT");      //(3)
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');  //(4)
  xhr.send(e.data);                      //(5)
  postMessage(xhr.responseText);         //(6)
}

 リスト6はWeb Workerの内容で、ここではクラウドサーバへ非同時通信で仕訳データを送信する処理を行っています。Web WorkerではJavaScriptのライブラリを使用できないため、生のAjaxによるコード記述になっています。

 Ajax通信では最初に非同期通信用のオブジェクトを生成する必要があり、これは(1)で行っています。その後(2)のopenメソッドで通信をオープンしていますが、第一引数ではPOSTメソッドでの通信であることを指定し、第二引数ではweb.xmlに記述されているgaedirectのChannelサーバアドレス指定、そして第3引数(false)では同期型で通信を行うことを指定しています。

 (3)はキャッシュデータの利用を回避して、Web サーバから毎回確実にレスポンスを受け取るようにするための記述です。

 (4)ではHTTPヘッダに追加する情報を指定していますが、POST通信ではHTTPデータ送信のペイロードにデータをセットして送信するため、そのデータフォーマットをサーバに知らせる必要があり、この指定を行います。GETメソッドの場合は、ペイロードは空になるため指定の必要はありません。

 以上の準備の後(5)のsendメソッドでデータを送信します。

 Ajaxの同期通信では、データ送受信の間sendメソッドでロックされ、サーバからのレスポンス受信が完了すると次のプログラムステップに移ります。(6)ではサーバレスポンスデータを引数にセットしてメインルーチンに処理完了を通知しています。

(3)サーブレットとビーンズプログラム

 今回サンプルでは、クラウドサーバとの送受信処理をバックグラウンドのWeb Workersから行うように変更していますが、その場合もクラウドサーバ側のプログラム処理(サーブレットとビーンズ)は前回とまったく同じです。従ってここでは省略しますが、必要な方は前回の記事を参照してください。

次のページ
ネットワーク送信のスピードアップとセキュリティモードでのデータ送受信

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Cloud SQLで学ぶ業務・基幹系アプリ再入門連載記事一覧

もっと読む

この記事の著者

清野 克行(セイノ カツユキ)

慶應義塾大学工学部電子物理専攻卒。日本IBM、日本HPで、製造装置業を中心とした業務系/基幹業務系システムのSE/マーケティングや、分散アプリケーションによる社内業務システム開発などに携わる。現在は、クラウドやAjax関連の/ソフト開発/書籍執筆/セミナー講師/コンサルティング、などを行っている。情...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6714 2012/08/21 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング