BLOG

【画面遷移せずにデータを取得できる】Ajax、非同期通信について

2020/09/30

TAKAYA OHTAOPERAのようにシームレスな画面遷移を実現する場合にAjaxが使われます。

SPA(Single Page Application)などデスクトップアプリのように操作できるのですが、それにもAjaxなどの非同期通信が使われています。具体的なサービスを挙げるとFacebookTwitterですね。

今回、Ajaxや非同期通信についてあんまり理解せずに使っていたのでまとめてみました。

目次

  1. 非同期通信とは?
  2. メリット・デメリット
  3. Ajaxの概要
  4. 方法
    1. JavaScriptで書いた場合
    2. jQueryで書いた場合
  5. まとめ
  6. 参考文献

非同期通信とは?

まず、ウェブページなどを閲覧するためにHTTP通信をしてますよね。
ざっくり説明すると、まずWebブラウザ(クライアント)がウェブサイト(サーバー)にHTTPリクエストを送ります
サーバーが処理を行い、その結果をブラウザに返すのがHTTPレスポンスです
ブラウザがそれを表示することで、ユーザーがウェブページを見ることができます。
この流れがHTTP通信です。

HTTP通信の処理の流れの図

同期通信はリクエストを出してからレスポンスを受け取るまで、他の処理を行うことができません。
それに対して非同期通信は、リクエストを投げてもブラウザの操作が行うことができます。そしてサーバーからレスポンスを受け取ると、受信処理を実行します。

ページの一部だけ変更するのに同期通信をしていたら、その間操作できないのでユーザビリティが損なわれますよね。
そんなときに非同期通信を使えば、ユーザビリティを損なうことなくページを更新することができます。

メリット・デメリット

次に非同期通信を使うメリット・デメリットをそれぞれ表にまとめてみました。

表1. 非同期通信のメリット

メリット 説明
操作性の向上 サーバーが処理を行っている間に操作できる点
パフォーマンスの向上 ページの一部のみ更新するため、通信量の削減
機能を実現しやすくなる 編集中の文章を一時保存するなどの機能を
ユーザーに意識させることなく実装することができる
表2. 非同期通信のデメリット

デメリット 説明
クロスブラウザ処理の必要 JavaScriptで異なるドメインのサービスに接続すると
エラーが起こるため 回避するための方法が必要
逆にサーバーの負荷が増える場合がある 不用意に非同期通信ばかり行っていたら、
サーバーの負荷が増える
コードがいつ処理されているのか分かりづらくなる コードの量が増えていくと
いつ非同期処理が実行されているか、分かりづらくなる

Ajaxの概要

Ajax(エイジャックス)とは、簡単に言ったらJavaScriptで非同期通信を行うことです。

Ajaxを使っているものを挙げるとGoogle マップが有名です。
地図をスライドするとその先の地図が表示されますよね。スライドしている間に足りない地図のデータをAjaxでリクエストしているから、ぬるぬる地図を動かすことができるのです。
もしAjaxがなければスライドする度にページを再読み込みする必要があるので、Ajaxに感謝です。

AjaxはHTML、XHTML、CSS、JavaScript、DOM、XML、XSLT、XMLHttpRequestオブジェクトなど既存の技術を組み合わせたものです。アプローチを指した言葉であり、Ajax自体がある種の技術という訳ではありません。

Ajaxは正式名称はAsynchronous Javascript And XMLです。XMLとありますがJSON、 HTML、テキストファイルなど、様々な形式の情報で送受信できます。最近ではXMLよりJSONの方がよく使われています。

Ajaxの処理の流れの図

方法

Ajaxを行う方法はいくつかあるのですが、今回はXMLHttpRequest APIを使う方法を紹介します。
最初にJavaScriptで書いた場合、次にjQueryで書いた場合を説明していきます。

JavaScriptで書いた場合

[common.js]

解説していきます。まずJavaScriptがサーバーにHTTPリクエストを送るために、XMLHttpRequestオブジェクトのインスタンスを作成します。

[common.js]

openメソッドでリクエストの初期化を行います。

引数は
・method: HTTPリクエストメソッド。 “GET”, “POST”, “PUT”, “DELETE”, など。
・url: リクエストの送り先のURL。
・async: 論理値。falseだと同期通信になる。既定値は true。
・user,password: ベーシックHTTP認証のユーザーとパスワード。既定値は null。
を取ります。

[common.js]

今回common.jsのパス/bar/foo.txtに対して、GET通信をしようとしています。

次にサーバーにリクエストを送ります。コードの順番と違うのですが、この部分ですね。

[common.js]

非同期の場合、リクエストが送信されるとメソッドはすぐ戻ります。結果は次のイベントによって配信されます。
同期の場合はメソッドはレスポンスを受け取るまで戻りません。

引数でリクエストの本文データを送ることができます。ただしリクエストメソッドがリクエストの本文を受け取れるものに限ります。リクエストメソッドが本文を受け取れない場合、引数は無視されてnullに設定されます。

最後にレスポンスに対するイベントハンドラを設定し、受動処理を指定します。

readyStateプロパティが変化するたびに、こちらの処理が走ります。
readyStateプロパティはXMLHttpRequestクライアントの状態を返します。要は非同期通信の状態を返しています。

XMLHttpRequestクライアントの状態について表にまとめてみました。

表3. XMLHttpRequestクライアントの状態

説明
0 XMLHttpRequestオブジェクトのインスタンスは作成済み。
openメソッドは呼び出していない
1 openメソッドが呼び出し済み(ロード中)
2 sendメソッドが呼び出し済み。
ヘッダーとステータスが利用可能
3 ダウンロード中。
レスポンスボディを受け取っている
4 取得操作完了。
データ転送が成功したか、失敗したかのどちらか

またstatusプロパティでHTTPステータスコードを取得しています。HTTPステータスコードとはサーバーのレスポンスの意味を表す3桁の数字コードです。これで非同期通信の処理の結果を取得してるのですね。
HTTPステータスコードの主な値を表にまとめてみました。

表4. 主なHTTPステータスコード

説明
200 OK。リクエストが成功。
HTTPメソッドにより成功の定義が異なる
401 Unauthorized。認証が必要
403 Forbidden。アクセス拒否。
401と違ってサーバーにクライアントの識別子が知られている
404 Not Found。リクエストされたソースが発見できない。
通信先が有効であるが、リソースが存在しない
500 Internal Server Error。サーバー側で処理方法がわからない事態が発生
503 Service Unavailable。サーバーがリクエストを処理する準備ができていない。
主な原因としてサーバーがメンテナンスや過負荷で落ちていることが挙げられる

今回は、HTTPステータスコードが200の値を返す(処理が成功)ときにサーバーから受け取ったテキストをコンソールに出力します。それ以外の値なら、レスポンスメッセージをコンソールに出力します。

[common.js]

jQueryで書いた場合

BRISKでは主にjQueryでAjaxを扱うことが多いです。jQueryでの基本の書き方を説明したいと思います。

[common.js]

オプションの説明を下の表でまとめました。

表5. $.ajax関数の各オプションまとめ

オプション名 説明
type HTTPリクエストメソッドを指定
GETかPOSTなど。初期値: GET
url リクエストを送信する先のURL
省略した場合、呼び出し元に送信
async 非同期通信フラグ
初期値: true(非同期通信)
falseだと同期通信になる
dataType サーバーからレスポンスされるデータの型を指定
返ってくるデータのMIMEタイプとの整合性をとる
値の例: xml、html、script、json、jsonp、text
timeout タイムアウト時間をミリ秒で指定
data サーバーに送信する値
オブジェクトが指定された場合、
クエリー文字列に変換されてGETリクエストとして付加される

$.ajax()はjqXHRオブジェクトを返します。jqXHRオブジェクトとはXMLHttpRequestオブジェクトのスーパーセットです。XMLHttpRequestオブジェクトを使いやすいように拡張したものみたいですね。

jqXHRオブジェクトはPromiseインターフェースを実装していています。なので受信したデータをコールバック関数で受け取ることなく、done()やfail()で取得できるのですね!

then()でもデータを取得できます。done()とfail()をまとめてかけるのがthen()です。

[common.js]

done()、fail()、always()の代わりにsccess()、error()、complete()で書いている場合がありますが、jQuery 1.8で非推奨になりました。

まとめ

サラッと書いてあるコードがこんな動きをしてたんですね。
調べながら書いていたのですが、ドンドン知らない単語が出てきて大変でした。Ajaxを理解するにはJavaScriptだけではなくHTTP通信の知識も必要で、Webの基礎知識が大切だと思いました。
リッチなサイトでは非同期処理はもはや欠かせないので、理解して使っていきたいですね。

これを読んで、少しでも非同期通信について理解が深まったら幸いです。

参考文献

MDN
現代の JavaScript チュートリアル ネットワークリクエスト XMLHttpRequest
jQuery.ajax()のまとめ
JavaScript 日本語リファレンス
jQuery 日本語リファレンス
山田祥寛,[改訂新版]JavaScript本格入門,技術評論社,2016