ajax通信とは？jQueryでの実装

ajax通信についてきちんと理解していなかったのでまとめる。
ajaxとは？というところから始まるため、jQueryの実装部分のみ興味がある方は<a href="https://qiita.com/charita/items/42089ea96a962149c157#jquery%E3%81%AB%E3%82%88%E3%82%8Bajax%E9%80%9A%E4%BF%A1%E3%81%AE%E5%AE%9F%E8%A3%85">こちら</a>まで読み飛ばしてください。

尚、ajaxの説明については<a href="https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9" target="_blank">こちらの記事</a>が大変わかりやすかったので、踏襲しつつ自分の言葉でまとめたり追加で調べたりしている。

# ajaxとは？
「Asynchronous JavaScript XML」の略。
Asynchronousとは、非同時性の、非同期のという意味で、「<b>非同期通信</b>」を実装するためのもの。

# 非同期通信
<b>画面遷移のない通信</b>のことで、LINEやGoogle Mapなどのサービスが例として挙げられる。
LINEを例に考えると、メッセージを送信した瞬間、画面遷移が発生することなくトークルームに送信したメッセージが表示される。
仮に同期通信であればメッセージを送信するたびに画面遷移が発生するため、毎回ストレスを感じるだろう。

またGoogle Mapでは、どこのエリアを表示しても画面遷移が発生することはなく、ロードのために一時的に画面が白くなるだけで指定のエリアを表示することができる。

#### 同期通信との比較でもう少し考えてみる。

両者の違いは以下。

・同期通信はリクエストが送られてから<b>レスポンスが返ってくるまで他の処理を実行できない</b>
・非同期通信はリクエストが送られてから<b>レスポンスを待っている間に他の処理を実行することができる</b>

LINEで考えると、同期通信の場合はメッセージが送信（リクエスト）された際、
そのメッセージがトークルームに反映（レスポンス）されるまで他の処理が行えないため、画面にロードが走ることになる。

一方、非同期通信の場合、送信したメッセージがトークルームに反映（レスポンス）されるのを待たずして他の処理が行える状態にある（＝ロードが走らない）、ということになる。
例えば動画を送信した際、アップロード処理の実行中に追加でメッセージを送信することができる。
これが同期通信であれば、動画の送信が完了するまでロードが走ることになり何もできない。

# いつ使うのか
代表例としては前述の通りチャットやマップサービスが挙げられる。
他にも、検索機能において入力内容に応じてリアルタイムでレコメンドを表示させたい場合や、ログの取得目的で、あるボタンがクリックされた際にロードすることなくデータを取得しDBに保存したい場合など、様々な用途で使われる。

# ajax通信の仕組み
冒頭で『「Asynchronous JavaScript XML」の略。』と述べたように、大前提としてJavaScriptを使用している。
具体的には、JavaScriptのHTTP通信機能である<b>XMLHttpRequest</b>を用いている。

#### XMLHttpRequestとは
非同期なデータの通信を実現するためのAPIのことで、JavaScriptで初めから定義されているオブジェクトである。
具体的なイメージでいうと、JavaScriptのイベント発火によってWebサーバへ新たにHTTPリクエストを送信することができ、サーバーにデータを通知したり、サーバから返送されたHTTPレスポンスをページ上に反映することができるもの。

なんだかわかったようなわからないような、、、
一番しっくりきたのは、<b>「ブラウザ上でサーバーとHTTP通信を行うためのAPI」</b>という表現。

本来サーバーとの通信をする際には、PHPなどのサーバーサイド言語の処理が必要となる。
例えばフォームに入力した内容を指定のパスに飛ばすと、そこで初めてサーバーとの通信が行われるからだ。

一方ブラウザに変化をつけるJavaScriptは、あくまでブラウザに表示された範囲でしか活躍することはできない。
ページ遷移することも、裏側でDBとやりとりすることもできない。
そこで、JavaScriptによってブラウザ上で取得したデータを<b>XML形式のオブジェクト</b>として送受信することで、サーバーとのやりとりを可能にするのが<b>XMLHttpRequest</b>である。

# なぜXML形式のオブジェクトにするのか
ここまで調べてみて、なぜXML形式のオブジェクトとして送受信するのか疑問だった。
というかその前にXMLとは、、、？となった。

#### XMLとは
> XMLは、文章の見た目や構造を記述するためのマークアップ言語の一種です。
主にデータのやりとりや管理を簡単にする目的で使われ、記述形式がわかりやすいという特徴があります。
https://hnavi.co.jp/knowledge/blog/xml/

XMLの正式名称は「Extensible Markup Language」で、日本語では「拡張可能なマークアップ言語」と訳される。
マークアップ言語といえばHTMLが思いつくが、それと同類とのこと。
実際に見てみたほうが早い。

```xml
<?xml version="1.0" encoding="Shift_JIS"?>
<?xml-stylesheet type="text/xsl" href="testxsl.xsl"?>
<おこづかい帳>
　<支出>
　　<内容>
　　　<日付>1月20日</日付>
　　　<交通費>780</交通費>
　　　<食費>980</食費>
　　　<嗜好品>250</嗜好品>
　　</内容>
　　<内容>
　　　<日付>1月21日</日付>
　　　<交通費>950</交通費>
　　　<食費>1200</食費>
　　　<嗜好品>300</嗜好品>
　　</内容>
　　<内容>
　　　<日付>1月22日</日付>
　　　<交通費>500</交通費>
　　　<食費>1500</食費>
　　　<嗜好品>250</嗜好品>
　　</内容>
　</支出>
</おこづかい帳>
```

このように、HTMLと同じくタグで文字列を囲って表現している。
大きな違いとしては、タグ名をこちら側で指定できるということだろう。

#### なぜXMLを使用？
XMLがどのようなものかということだけ理解した上で、改めてなぜXMLを使用するのか。
それは、<b>記述方式が世界標準で統一されている</b>ため、データをXML化することであらゆるコンピュータシステムに応用ができるから。
JavaScriptでサーバーとやりとりをするためには、JavaScriptではなく共通言語を使う必要があるからである。

# JSON
前段でXMLの必要性について見てきたが、実のところ今ではXMLより<b>JSON</b>が使われている。
ajaxは「Asynchronous JavaScript XML」の略だが、XMLを使用しなくても良いらしい。

JSONもXMLと同じく<b>プログラミング言語問わず利用可能</b>であり、
データをダグで囲んで扱うXMLよりコードの記述量が少なく、データの読み込みが早くなるためJSONが主流となっているようだ。

JSONとは「JavaScript Object Notation」の略で、そのまま訳すと「JavaScriptオブジェクト記法」ということになる。
XMLではデータをタグで囲って扱っていたが、JSONは<b>JavaScriptのオブジェクト形式</b>で扱うことができる。
JavaScriptのオブジェクト形式というのは以下のような形式だ。

```javascript
let obj = {name: 'taro', age: 20};
```

JSONもこのような形式で表記される。
一点異なる点があるとすれば、<b>ダブルクオートのみ使用可能</b>ということと、<b>キーもダブルクオートで囲む必要がある</b>ということだ。
以下のようになる。

```javascript
let obj = {"name": "taro", "age": 20};
```



# jQueryによるajax通信の実装
jQueryでajaxを実装するには<b>ajax関数</b>を使用する。
以下3通りの記述法があるがどれでも実装できるため、記述量が一番短い③を使用する。

```
①window.jQuery.ajax(プロパティ)
②jQuery.ajax(プロパティ)
③$.ajax(プロパティ)
```

上記のプロパティの部分に色々と設定することで、<b>「どこに・どんなデータを・どんな形式で送るのか」</b>など他にも様々な指定ができる。
プロパティに記述する項目は決まっているわけではなく、必要に応じて記述する。
以下、具体的なコードで見てみる。

```javascript
$.ajax({
  headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')   //headerの設定（laravel使用時の例）
  },
  type: "POST",   //HTTPメソッド
  url: "example.php",   //データの送信先
  data: { "name": "John", "location": "Boston" },   //送信するデータ
  contentType: "application/x-www-form-urlencoded; charset=UTF-8",   //送信するデータの型、種類
  dataType: "json"   //レスポンスの型、種類
})
// Ajaxリクエストが成功（ステータスコード200）した場合の処理
  .done(function() {
    console.log('成功');
  })
// Ajaxリクエストが失敗した場合の処理
  .fail(function() {
    console.log('失敗');
  });

```

上記はあくまでほんの一例に過ぎず、気になる方は調べていただくことをお勧めします。
とはいえ、基本的には<b>type、url、data</b>があればたいていのことは実装は可能かと思う。
順を追って見ていく。

<b>header</b>
リクエストheaderに追加したい要素がある場合に記述する。
例に挙げたものはLaravelで`POST`する際に必須となるもの。

<b>type</b>
サーバーへのリクエストのHTTPメソッドを指定する。
デフォルト値は`GET`。
`PUT``PATCH``DELETE`等も指定することができるが、全てのブラウザでサポートされていないため推奨されていない。

<b>url</b>
送信先のファイル名、パス、URLのいずれかを指定。
ファイル名はそのままで、同一プロジェクト内のどのファイルにリクエストを送信するか。
パスはルーティングとの対応を確認する。
URLは`https://example.com`のような形で、外部ドメインへの送信が可能である。（クロスドメインの設定に注意）

<b>data</b>
リクエスト先に送信するデータを指定。
例に挙げたようにJSON形式で記述する。
変数を指定しても中身がJSON形式となっていれば問題ない。

<b>contentType</b>
送信するデータの型を指定。
デフォルト値は`application/x-www-form-urlencoded`で、基本的にはこのままでまず問題ない。

「タイプ/サブタイプ」という記載の仕方で、「タイプ」でデータの種類（テキスト、画像、動画など）を定義し、「サブタイプ」で具体的なデータ形式を定義している。
`text/plain, text/html, application/json `のようになる。

`application/x-www-form-urlencoded`は、エンコードされたURLでデータが送受信される。
どうやらPHPの`$_POST`などで受け取るときにこの設定である必要があるみたいだが、
そもそもJSONでデータを送信するんじゃないの？という疑問が解消されない、、、
知見のある方がいらっしゃればコメントいただけると幸いです。

<b>dataType</b>
サーバーから返されるデータの型を指定。
省略した場合は、jQueryがMIMEタイプ[^1]などを見ながら自動的に判別する。

dataTypeを指定した場合、何かしらデータが奇形であると判断されるとエラーになるため、MIMEタイプ判定に任せてdataTypeの設定自体をなくすとエラーが解消することもある。
指定可能な値は次のようなもの。

[^1]: リクエスト⇔レスポンス間でやりとりするデータの種類を示す情報のこと。<br>textなのかHTMLなのかJSONなのか画像なのかなどの情報のことで、前述のcontentTypeとほぼ同義。


>"xml": XMLドキュメント
"html": HTMLをテキストデータとして受け取る。ここにscriptタグが含まれた場合、処理は実行されます。
"script": JavaScriptコードをテキストデータとして受け取る。cacheオプションに特に指定が無ければ、キャッシュは自動的に無効になります。リモートドメインに対するリクエストの場合、POSTはGETに変換されます。
"json": JSON形式のデータとして評価し、JavaScriptのオブジェクトに変換します。
"jsonp": JSONPとしてリクエストを呼び、callbackパラメータで指定した関数に呼び戻された値をJSONデータとして処理します。(jQuery 1.2より追加)
"text": 通常の文字列。

以上のような内容を適宜設定し実装することでajax通信が可能となる。

仕事でちゃんと使ってみて、とんでもなく便利な技術だと感じた。
これからどしどし使っていこうと思う。