LoginSignup
20
25

More than 5 years have passed since last update.

メッセージ投稿で非同期通信を実装

Last updated at Posted at 2018-05-10

非同期通信とは?

こんなのとか、

こんなのができる仕組みです。

要は、↑のようなページの更新なしで画面をスラスラ処理できる仕組みを非同期通信と言います。

どうしてできるのか

非同期通信の内容を理解するために、クライアント・サーバー通信の方式で対をなす同期通信との対比を書きます。

同期通信

同期通信はデータ通信のリクエストを出してからレスポンスが来るまでほかの処理を行わずにレスポンスを待ち続ける

非同期通信

非同期通信ではレスポンスを待っている間にほかの処理を行える。ほかの処理を行っている際に、レスポンスを受信すると受信処理を実行する。

一言でまとめると、サーバーからのレスポンスを待たずにブラウザで操作できるようにしているからです。

Ajax

これを実現するのがAjaxというエンジンです。エンジンといってもJavaScriptとXMLというテキストデータの組み合わせです。
「Asynchronous JavaScript + XML」という構成要素から成るエンジンなのですが、 これのおかげで非同期通信を実現しています。

参考:
http://wa3.i-3-i.info/word12672.html

コメント投稿の非同期通信

実際のコメント投稿機能を作った際のソースを記載します。

show.html.rb
## コメントを表示するviewファイル
<div class ="contents row">
  <div class="content_post" style="background-image: url(<%= @tweet.image %>);">
    <% if user_signed_in? && current_user.id == @tweet.user_id %>
      <div class="more">
        <span><%= image_tag 'arrow_top.png' %></span>
        <ul class="more_list">
          <li>
            <%= link_to '削除', "/tweets/#{@tweet.id}", method: :delete %>
          </li>
        </ul>
      </div>
    <% end %>
    <%= simple_format(@tweet.text) %>
    <span class="name">
      <a href="/users/<%= @tweet.user.id %>">
        <span>投稿者</span><%= @tweet.user.nickname %>
      </a>
    </span>
  </div>
  <div class="container">
    <% if current_user %>
      <%= form_tag("/tweets/#{@tweet.id}/comments", method: :post, id: "new_comment") do %>
        <textarea cols="30" name="text" placeholder="コメントする" rows="2" class ="textbox"></textarea>
        <input type="submit" value="SENT">
      <% end %>
    <% end %>
    <div class="comments">
      <h4><コメント一覧></h4>
      <% if @comments %>
        <% @comments.each do |comment| %>
          <p>
            <storng><%= link_to comment.user.nickname, "/users/#{comment.user_id}" %>:</strong>
            <%= comment.text %>
          </p>
        <% end %>
      <% end %>
    </div>
  </div>
</div>
products/search.json.jbuilder
#↓ jbuilderを使って入力データをJSON形式で出力し、JavaScriptに渡す。
json.array! @products do |product|
  json.id product.id
  json.title product.title
  json.image product.image_url
  json.detail product.detail
end
comments_controller.rb
class CommentsController < ApplicationController
  def create
    @comment = Comment.create(text: comment_params[:text], tweet_id: comment_params[:tweet_id], user_id: current_user.id)
#↓respond_toでリクエストされたフォーマットによって処理を分岐
    respond_to do |format|
      format.html{redirect_to tweet_path(params[:tweet_id])}
      format.json
    end
  end

  private
  def comment_params
    params.permit(:text, :tweet_id)
  end
end
assets/javascripts/comment.js
// ↓コメントを出力する関数を定義
$(function(){
  function buildHTML(comment){
    var html = `<p>
                  <strong>
                    <a href = /users/${comment.user_id}>${comment.user_name}</a>:
                    </strong>
                    ${comment.text}
                    </p>`
    return html;
  }

// ↓送信ボタンクリック時にイベント発火
$("#new_comment").on("submit",function(e){
//↓e.preventDefaultで送信ボタンクリック時の通信を止める 
    e.preventDefault();
    console.log(this)
// ↓formDataでフォームの情報を取得
    var formData = new 
FormData(this);
// ↓非同期通信でコメントが保存されるようにする
    var url = $(this).attr("action")
    $.ajax({
      url:url,
      type:"POST",
      data:formData,
      dataType:"json",
      processData:false,
      contentType:false
    })
//↓ 非同期通信成功時に上で定義した関数を実行
    .done (function(data){
      var html = buildHTML(data);
      $(".comments").append(html)
      $(".textbox").val("")
    })
//↓エラー時の処理
    .fail(function(){
      alert("error");
    })
  })
})```

処理の流れ

全体の流れをざっくりまとめると、以下のようになります。
①viewからコメントを送信
②JS上でコメントの送信を中止、JSON形式への変更リクエスト
③Controllerがリクエスト別で処理を分岐(今回はJSON)
④jbuilderがデータをJSONに変換
⑤JSで表示を実行

image.png

まとめ

非同期通信とは、ページの更新なしで画面をスラスラ処理できる仕組みである
非同期通信の仕組みとは、サーバーからのレスポンスを待たずにブラウザで操作できるようにしていることである
非同期通信を実現するものは、Ajaxである
Ajaxを使うと、JS上で表示の処理を柔軟に変えられる

20
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
25