#非同期通信(Ajax)とは
画面の遷移のない通信を非同期通信という。
リクエスト後にレスポンスが返ってきた際、ブラウザが再読み込みされること無く通信が行われる通信方法で、非同期通信は英語で"Asynchronous JavaScript + XML"と表現され、略してAjax(エイジャックス)と呼ばれる。
Ajaxでは、レスポンスのデータにJSONという形式が使われることが多い。
##同期通信と非同期通信の違い
同期通信・・・webブラウザからサーバーにリクエストを通信しレスポンスが返ってくる時に、全ての情報を通信しているので画面が一瞬白くなり、サーバーからレスポンスが返ってくるまでは他の作業ができない
非同期通信・・・ブラウザから一部の情報をリクエストするのでそれ以外の部分は変わらないため画面が白くなることはない。そのため、サーバーからレスポンスが返ってこなくても他の作業ができる。
##JSON
Java Script Object Notationの略で、データ交換を行うためのデータ記述形式の一種。Rubyのハッシュと同様、キーとバリューの組み合わせでデータを表現する形式。
{user_name: "testさん", created_at: "2019-08-28T10:35:13.000+09:00", content: "これがJSONの形です!", image_url: null, id: 6}
Ajaxでは主にJSONという型でレスポンスが行われる。この時ブラウザではJavaScriptが動作し、JavaScriptはサーバからJSON形式で返されたデータをHTMLに成形、ブラウザを書き換える。この仕組みにより、ブラウザの一部だけを更新することが可能になる。
####簡単なToDoアプリで動きの確認
###非同期通信 実装のポイント
####1. 非同期通信ではJavaScriptを利用してリクエストを行う
非同期通信ではJavaScriptのメソッドを利用してリクエストを送る。そのため、フォーム要素のデフォルトアクションを無効にする必要がある。
またこの時、リクエストに対してのレスポンスはJSON形式で返してほしい旨をリクエストに含める。
####2. コントローラでJSON形式のデータを用意するよう準備
同期通信の際は特に指定せずともHTML形式のデータを返すようRailsが動いてくれる。
非同期通信をする際は、リクエストにJSON形式で返してほしい旨の情報が含まれているため、その場合の対処をコントローラのアクションに明記する必要がある。
####3. レスポンスするためのJSON形式のデータを準備
同期通信ではviewsディレクトリの中に○○.html.erbという形式でHTMLのファイルを準備して置くことでレスポンスとしてHTMLを返すことができた。
非同期通信の場合、JSONのデータをレスポンスとして返す必要がある。短いデータであればコントローラ内に直接書けるが、同期通信の際と同様viewsフォルダの中にJSON形式のファイルを準備することもできる。この時のファイル名は、○○.json.jbuilderという形式になる。
####4. JavaScriptでレスポンスを受け取り、HTMLを操作してToDoを追加
同期通信におけるレスポンスはHTML形式であり、受け取ったHTMLを描画するためにブラウザは一度リロードされる。
対して非同期通信では、ページがリロードされることはなく代わりに、レスポンスとして返ってきたJSONのデータを利用してHTMLを操作する。
JSONのデータはユーザーが投稿したToDoのデータなので、これをToDoリストの一番後ろに付け加えるようJavaScriptを書く。
####respond_to
Railsのコントローラーで利用できる respond_to というメソッドは、「リクエストがHTMLのレスポンス求めているのか、それともJSONのレスポンス求めているのか」を条件に条件分岐してくれる。
respond_to do |format|
format.html { render ... } # この中はHTMLリクエストの場合に呼ばれる
format.json { render ... } # この中はJSONリクエストの場合に呼ばれる
end
HTMLを返す場合は、該当するビューを呼びその中でデータを生成していたが、JSONを返す場合はRubyのハッシュをrenderメソッドの引数として渡すだけでJSONに変換される。以下のようにコントローラーから直接データを返すことができる。こちらは、renderというメソッドに{json: { id: @user.id, name: @user.name }}というハッシュを引数として渡している。
respond_to do |format|
format.json {
render json: { id: @user.id, name: @user.name }
}
end
####JSONでレスポンスできるようにする
def create
@todo = Todo.create(todo_params)
respond_to do |format|
format.html { redirect_to :root }
format.json { render json: @todo}
end
end
JavaScriptを記載して送信時に要素を取得する
Ruby on Railsでは、アプリケーション作成時にjquery-railsというgemをインストールし、assetsディレクトリ以下のapplicaton.jsファイルで//= require jqueryこのように記述することでjQueryを読み込んでいる。
todo.jsというファイルをassets/javascripts以下に作成する。
####非同期通信でリクエストを行う
処理の流れ
- フォームの送信が行われた時にAjaxによる非同期通信を始める
- フォームに入力された値を取得する
- Ajaxを行う記述をする
- TodosコントローラのcreateアクションにてTodoの保存を行う
- 処理後にjsonを返す
- 非同期通信の終了後に受け取ったjsonを利用してHTMLを構築する
- 4で構築したHTMLをViewに差し込む
$(function() {
$('.js-form').on('submit', function(e) {
e.preventDefault();
var todo = $('.js-form__text-field').val();
# jQueryで非同期通信を行うための記述。
$.ajax({
type: 'POST',
url: '/todos.json',
data: {
todo: {
content: todo
}
},
dataType: 'json'
})
#非同期が成功したときに行う処理
.done(function(data) {
var html = $('<li class="todo">').append(data.content);
$('.todos').append(html);
$('.js-form__text-field').val('');
})
#非同期が失敗したときの処理
.fail(function() {
alert('error');
});
});
});