※この記事はrails初学者の方に向けて書いたものです。間違った解釈などあればご指摘いただければ幸いです。
非同期通信とは?
非同期通信とは、コンピュータ間で送信者のデータ送信タイミングと受信者のデータ受信タイミングを合わせずに通信を行う通信方式である。 つまり、送信者と受信者の両方がオンラインである必要がなく、片方が接続しているだけで通信が成立する。 非同期通信の対義語として、同期通信というものがある。
分かりやすく言うと、、、
相手に要求を出したら、(相手からの応答を待たないで)さっさと次の処理を進めることができる通信と表現できる。
非同期通信では、相手に要求(リクエスト)を投げたら、応答(レスポンス)が返ってくるまで待ちません。 通信というのは基本的にキャッチボールです。 相手に「要求」を投げて、「応答」を受け取ります。 要求を投げてから応答を受け取るまでには時間がかかります。要求の投げ方は2種類存在します。
1,応答が来るまで、何も処理を行わず待つ→同期通信
2,応答を待たずに、処理を進める→非同期通信
非同期通信を使用するメリット
メリット | 説明 |
---|---|
操作性の向上 | サーバーが処理を行っている間に操作できる |
パフォーマンスの向上 | ページの一部のみ更新するため、通信量の削減が可能 |
機能を実現しやすくなる | 編集中の文章を一時保存するなどの機能をユーザーに意識させることなく実装することができる |
バックエンドエンジニアを目指す際のポートフォリオに積極的に実装することで「サーバーへの負担」や「UXの向上」にまで気を遣っているのだというアピール材料になるそうなので今一度その概要をアウトプットしたいと思います。ここでは簡単な投稿アプリを作って動作確認をしながら非同期通信の基本的流れをおさらいしたと思います。
開発環境
・Rails: 6.1.3.1
・ruby: 2.7.2
・jquery: 3.6.0
手順
1, アプリの準備
$ rails new ajax_sample
$ cd ajax_sample
$ rails g controller posts index
$ rails g model Message title:string content:text
$ rails db:migrate
2,bootstrapの導入
以下の記事を参考に導入しました。今回は本筋からそれてしまうので割愛します。
・Rails 6にjQueryとBootstrapを入れる
3,postsコントローラの設定
class PostsController < ApplicationController
def index
@posts = Post.all
@post = Post.new
end
def create
Post.create(post_params)
@posts = Post.all
# redirect_toの代わりに入れる
end
private
def post_params
params.require(:post).permit(:title, :content)
end
end
4,ルーティングの設定
Rails.application.routes.draw do
root 'posts#index'
resources :posts, only: [:index, :create]
end
5,viewの作成
まずは投稿一覧画面に各記事を表示する部分テンプレートの_post.html.erbと投稿用のフォームとしてモーダルを配置します。
<div class="container mt-5">
<div class="row">
<div class="col-3 sidebar">
<button type="button" class="btn btn-primary w-100" data-toggle="modal" data-target="#exampleModal">
投稿
</button>
</div>
<div class="col-9 sidebar posts">
<%= render 'posts', posts: @posts %>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">新規投稿</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<%= form_for @post, remote: true do |f| %>
<div class="modal-body">
<div class="form-group">
<%= f.label :title, "タイトル" %>
<%= f.text_field :title, class:"form-control" %>
</div>
<div class="form-group">
<%= f.label :content, "本文" %>
<%= f.text_area :content, class:"form-control" %>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
<%= f.submit "投稿する", class:"btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
モーダルのデザインはbootstrapのチートシートから持ってきたものにアレンジを加えただけです。
・Modal - Bootstrap 4.2 - 日本語リファレンス
次にindex.html.erbに配置した部分テンプレートを用意します。この中にはpostsテーブルの各要素を表示するためにeachメソッドを使用しています。
<% posts.each do |post| %>
<div class="card mb-1">
<div class="card-body">
<p class="card-text"><%= post.title %></p>
<p><%= post.content %></p>
</div>
</div>
<% end %>
これで投稿一覧はひとまず表示することはできますが、このままでは非同期処理にはできません。同期処理であればpostsコントローラにredirect_toメソッドを記述して再度投稿一覧を描画し直せばいいのですが今回はページ遷移をなくしたいので追加でjavascriptのファイルが必要です。
$("textarea").val("");
$("input").val("");
$('#exampleModal').modal('hide')
$('.posts').html("<%= escape_javascript(render 'posts', posts: @posts) %>")
上記のファイルでは投稿フォームのリセット、モーダルウィンドウの終了、新しい投稿一覧の書き換えを行っています。
終わりに
非同期通信は実装できれば画面遷移でユーザーにストレスを与えることもサーバーに必要以上に負荷をかけることなくサービスを運用できるため重宝されているそうです。まだまだ私も理解が追いついていない部分も多いので今後も積極的に実装していこうと思います。