Web ページ内の JavaScript プログラム動作中に、 新たにサーバとの非同期通信を開始して表示中のページを動的に変える方式を Ajax とよぶ。以下の HTML 文書と JavaScript プログラムは、ユーザからの入力をCGI経由と Ajax で呼ぶ2つを比較するためのものである。
<!DOCTYPE html> <html lang="ja"> <head> <title>例: Access DB via CGI</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body> <h1>DB Access</h1> <h2>via CGI</h2> <form method="POST" action="./db.cgi"> <table> <tr><td>タグ:</td><td><input id="tag" name="tag"></td></tr> <tr><td>数値:</td><td><input id="val" name="value"></td></tr> </table> <p><input type="submit" value="CGIで送信"> / <button id="js-sub" type="button">AJAXで送受信</button></p> </form> <p>Result: <span id="result"></span></p> <p id="all"></p> <script type="text/javascript" src="../src/db-post.js" charset="utf-8"></script> </body> </html>
#!/usr/bin/env ruby22
# -*- coding: utf-8 -*-
require 'cgi'
require 'json'
require 'sqlite3'
dbfile = './db/data.sq3'
c = CGI.new({'accept_charset' => 'utf-8'})
#print "Content-type: application/json; charset=UTF-8\n\n"
print "Content-type: text/plain; charset=UTF-8\n\n"
value = c['value'].to_f
tag = c['tag']
now = Time.now.to_s
db = SQLite3::Database.new(dbfile)
db.busy_timeout = 1000
db.execute("CREATE TABLE IF NOT EXISTS foo(tag text, time text, val real);")
db.execute("INSERT INTO foo VALUES(?, ?, ?);", tag, now, value)
val = {'タグ'=>tag}
val['合計'] =
  db.execute("SELECT sum(val) FROM foo WHERE tag=?", tag)[0][0].to_f
val['平均'] =
  db.execute("SELECT avg(val) FROM foo WHERE tag=?", tag)[0][0].to_f.round(2)
res = db.execute("SELECT val FROM foo WHERE tag=?", tag)
val['全件'] = res.collect{|row| row[0]}		# 先頭カラムを集める
puts JSON.pretty_generate(val)
// 例: AJAX的CGI通信
function dbAccess() {
    function submit() {
	// https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
	var val = document.forms[0].elements['value'];
	var tag = document.getElementById('tag');
	var body = JSON.stringify({val: val.value, tag: tag.value})
	if (val) {
	    fetch('./db.cgi', {
		method:	 "POST",
		headers: {'Content-Type': 'application/json; charset=utf-8'},
		body: body,
		// mode: "cors", cache: "no-cache",credentials:	"same-origin",
	    }).then(function(resp) {	// サーバからの結果が来たらここに来る
		return resp.json();
	    }).then(function(rj) {	// JSONが取得できたらここに来る
		var str = '合計:'+rj['合計'] + ' 平均:'+rj['平均']
		var all = '全件: ' + rj['全件'].join(', ')
		document.getElementById('result').textContent = str; //書き込む
		document.getElementById('all').textContent = all;
	    })
	}
    }
    document.getElementById('js-sub').addEventListener('click', submit);
}
document.addEventListener('DOMContentLoaded', dbAccess)
db-post.js のうち Ajax的データ送信を行なうのが 
submit 関数である。
fetch() メソッドにURLとリクエスト状態を表す
 ハッシュを渡すthen() でサーバ応答が来た場合の受信関数を書く
 (JSON値を返す処理を書けばよい)then() で得られるJSON値により実処理を進めるという流れで行なう。送信するデータはCGIが受け取るためには、
渡したい値の集合をJSON形式で格納し、それを
JSON.stringify() メソッドで文字列化したものを
サーバプログラムに送信する。たとえば
var body = JSON.stringify({
  変数1: 値1
  変数2: 値2
})
のようにJSON値を作成したら、これをfetch()
メソッドへの第2引数のハッシュの body
キーに対応する値として設定する。
これがJavaScriptプログラム中の以下の部分である。
fetch('./db.cgi', {
  method:	 "POST",
  headers: {'Content-Type': 'application/json; charset=utf-8'},
  body: body	// bodyキーにbody変数の値を設定
})
CGIプログラムでは、db/data.sq3
をデータベースファイルとして利用するようになっている。
実際に動かす前には、httpd に書き込み可能となるディレクトリを作成し、
そこにダミーのデータベースファイルを作成する。
mkdir -m 1777 db touch db/data.sq3 chmod 666 db/data.sq3
また、CGI処理が可能となるよう、同じディレクトリ内に
.htaccess というファイルを作成し、以下の内容とする。
Options +ExecCGI AddHandler cgi-script .cgi
ユーザID、ユーザ名、東経、北緯、
ゴールとなる位置(LatLng)は、goal.txt ファイルに入れておく。