#はじめに
Ajaxとは、「JavaScriptを使って非同期でサーバーと通信を行う手法」です。(読みはエイジャックス)
この記事では基本動作の流れ、重要用語の説明を記述しています。初学者の方の理解の助けになればと思います。稚拙ではありますがGoogle Maps APIを使ったミニアプリも実例として、載せていますので、誰かの助けになれば嬉しいです。
AjaxはAsynchronous JavaScript + XML の略称。
※ Asynchronous【発音:ア・シンクロナス】 シンクロ(同期)の否定と思えばイメージが掴みやすいかな。
#Ajax基本動作の流れ
①任意のボタンでイベント発生
②JavaScript + XMLHttpRequestでサーバーに対してリクエストを送信(非同期処理)
③サーバーで受け取った情報を処理
④処理結果はJSONやXMLなどの形式で応答
⑤受信したレスポンスを受けて、DOMでページを更新。
上記に出てきた用語をきちんと理解できると何をやっているのか見えてくると思います。
各用語について説明していきます。
#用語説明
###同期
クライアントがHTTPリクエストを送った後、HTTPレスポンスがサーバーから返ってくるまで待機することになる。ネットワークが遅い場合に、ページが真っ白になることがある。あの状態。ユーザーはその間操作不可。
HTTPリクエスト:クライアントからwebサーバーへの通信
HTTPリクエスト:webサーバーからクライアントへの応答
参考:https://itsakura.com/network-http-get-post
###非同期
HTTPリクエストを送った後、放置して他の作業を進めておき、HTTPレスポンスが返ってきたタイミングで、その後の処理を再開する。ページ全体の動作を止めることがなく、ページの一部を更新することが可能。ユーザーを待たせるストレスを感じることなく、他の作業を進めることができる。
###DOM
Document Object Model「ドキュメントオブジェクトモデル」の略。HTML文書およびXML文書のためのAPI。JavaScriptからHTMLを自在に操作する仕組みのこと。HTMLやXMLを「ツリー構造」として展開し、アプリケーション側に文章の情報を伝え、加工や変更をしやすくする。
API:
Application Programing Interfaceの略。アプリケーションをプログラミングするための何かとつなぐインターフェース。APIがソフトウェアやアプリケーションなどの一部を外部に向けて公開することで、第三者が開発したソフトウェアと機能を共有できるようにするもの。
###XMLHttpRequest(XHR)
JavaScriptでHTTP通信を行うためのAPI。XMLHttpRequestはWEBサーバから一度すべてのデータを読み込んだ後でもデータの送受信を行うことができるため、ページをリロードすることなくページ内容を書き換えることが可能。
###JSON
JavaScript Object Notationの略。JavaScript のデータ定義文をベースとした、簡易的なデータ定義言語。JSONは文字列のため、ネットワークを通してデータを転送したい場合に便利。JSONデータへアクセスしたい場合は、JavaScriptオブジェクトへ変換する必要があるが、JavaScriptにはJSONとJavaScriptオブジェクトを相互に変換できるJSONメソッドがある。以前は共通データ定義言語としてXMLが利用されてきたが、簡易的なJSONが利用されるケースが増えてきている。
参考:JSONについて
・http://www.tohoho-web.com/ex/json.html
・https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/JSON
・https://techplay.jp/column/611
#実例(Ajaxを用いた通信)
このミニアプリの動作の流れ
①ユーザーがフォームに郵便番号を入力
②自動入力ボタンを押すとイベント発生(setState())。Ajaxを用いて、Google Maps APIへリクエスト。
③レスポンスが正しく返ってきたら、住所をフォームに自動入力し、マップを表示。
実務未経験のためコードは荒いですが、動作は確認済みです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>郵便番号検索</title>
<!-- viewport meta -->
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<style>
h1 {
padding:30px;
}
#map {
height: 300px;
}
</style>
<body>
<div class="container">
<div class="row justify-content-center">
<h1>郵便番号検索</h1>
<div class="col-md-12">
<div class="content">
<label for="zip" class="col-md-4 text-md-right">郵便番号</label>
<input id="zip" name="zip" type="text">
<input type="button" value="自動入力" onClick="setState()">
</div>
<div class="content">
<label for="state" class="col-md-4 text-md-right">都道府県</label>
<input id="state" name="state" type="text">
</div>
<div class="content">
<label for="city" class="col-md-4 text-md-right">市町村</label>
<input id="city" name="city" type="text">
</div>
<div class="content">
<label for="address" class="col-md-4 text-md-right">番地</label>
<input id="address" name="address" type="text">
</div>
</div>
<h1>地図表示</h1>
<div class="col-md-12">
<div class="content">
<label for="addressAll" class="col-md-4 text-md-right">表示している住所</label>
<span id="addressAll" name="addressAll" type="text"></span>
<div id="map"></div>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://maps.googleapis.com/maps/api/js?key={your_API_key}&callback=initMap" async defer></script>
<script>
//郵便番号から住所を取得
function setState() {
var zip = $('#zip').val();
//バリデーション
var pattern = /^\d{3}-?\d{4}$/g;
var result = zip.match(pattern);
//入力異常時の処理
if((zip == "") || (result == null) ){
alert('再度入力ください');
}
$.ajax({
type : 'get',
url : 'https://maps.googleapis.com/maps/api/geocode/json',
crossDomain : true,
dataType : 'json',
data : {
address : zip, //APIへ送る郵便番号のデータ
language : 'ja',
sensor : false,
key : '************************'
},
success:function(response){
if(response.status == "OK") {
////-------- 住所検索・表示 --------/////
var obj = response.results[0].address_components;
//値を配列に格納
var value = [];
for (var i=1; i<=3; i++) {
value[i] = obj[i]['long_name'];
}
//値を表示
$('#state').val(value[3]); // 都道府県
$('#city').val(value[2]); // 市町村名
$('#address').val(value[1]); // 番地
$("#addressAll").empty(); //値の中身を削除(複数回検索すると連なるため)
$('#addressAll').append("〒"+zip+" "+value[3]+value[2]+value[1]);
//mapを生成する関数を呼び出す
initMap();
}else{
alert('住所情報が取得できませんでした');
}
////-------- マップ表示 --------/////
function initMap() {
// 緯度・経度を変数に格納
var lat = response.results[0].geometry.location.lat;
var lng = response.results[0].geometry.location.lng;
//表示するマップのセンター
var center = new google.maps.LatLng(lat,lng);
//マップのオプション
var options = {
zoom: 18, //地図のズームを指定
center: center
};
//地図を表示
var map = new google.maps.Map(document.getElementById("map"), options);
// マップにマーカーを表示
var marker = new google.maps.Marker({
map : map,
position : center
});
}
}
})
}
</script>
</body>
</html>
⭐️困った時用の殴り書きメモ
Google Maps APIのレスポンス
・statusは検索結果のステータス。検索結果の成功と失敗を判定。
・resultsは検索結果の情報を配列として持っている。
・geometryは場所の情報を持つlocation、検索対象範囲を示すviewportなどで構成。
・オブジェクトの中身を取り出していく時はconsole.log()
で中身を確認して取得していけば難しくはない。
・レスポンスが返ってこなければ、APIキーの制限に問題ないか確認。
参考:レスポンスで返ってくるオブジェクト
・https://developers.google.com/maps/documentation/geocoding/overview?hl=ja#ComponentFiltering
・https://vintage.ne.jp/blog/2015/04/395
参考:Google Maps APIキー制限
https://maps.multisoup.co.jp/blog/2967/
その他参考:
https://www.codegrid.net/articles/2014-ajax-1/#toc-4
https://api.jquery.com/jQuery.ajax/
#最後に
初学者がより理解を深めるためにまとめました。
AjaxはAPIと通信するときに使うと思うので学習必須だと思っています。
今後も記事を更新して、より深みを出していきます。
(もしこの記事に誤りがありましたらご教授いただけると幸いです。)