LoginSignup
0
2

More than 3 years have passed since last update.

エラー解決  Javascript 非同期通信によるメッセージの自動更新機能の実装

Last updated at Posted at 2020-01-15

javascriptのエラー解決に苦心したので、その記録。

状況

チャットアプリのメッセージ機能の更新を非同期通信上で、実施しようとしたところ、
投稿まで非同期で通信できなくなった。

問題のjsファイル
(function(){
  var buildHTML = function(message){
    console.log(message)
    if (message.image){
      console('1')
      var html =  
        `<div class = "message" data-message-id=${message.id}>
        <div class="messages__message" >
          <div class="messages__message__info">
            <div class="messages__message__info__member">
              ${message.user_name}
            </div>
            <div class="messages__message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="messages__message__text">
            <p class="messages__message__text__content">
              ${message.content}
            </p>
          </div>
          <img src=${message.image} >
        </div>`
        return html;
    } else {
      console.log('2')
      var html =
        `<div class = "message" data-message-id=${message.id}>
        <div class="messages__message" >
          <div class="messages__message__info">
            <div class="messages__message__info__member">
              ${message.user_name}
            </div>
            <div class="messages__message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="messages__message__text">
            <p class="messages__message__text__content">
              ${message.content}
          </p>
        </div>`
        return html;
    };
  }

    $('.new_message').on('submit', function(e){
    e.preventDefault();
    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){
      console.log(data)
      var html = buildHTML(data);
      $('.middle').append(html);
      $('form')[0].reset();
      $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
      $('input').prop('disabled', false);
    })
    .fail(function(){
      alert('メッセージ送信に失敗しました');
    })
  })

  var reloadMessages = function() {
    //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
    last_message_id = $('.message:last').data("message-id");
    $.ajax({
      //ルーティングで設定した通りのURLを指定
      url: "api/messages",
      //ルーティングで設定した通りhttpメソッドをgetに指定
      type: 'get',
      dataType: 'json',
      //dataオプションでリクエストに値を含める
      data: {id: last_message_id}
    })
    .done(function(messages) {
      console.log(messages)
      if (messages.length !== 0) {
        //追加するHTMLの入れ物を作る
        var insertHTML = '';
        //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
        $.each(messages, function(i, message) {
          insertHTML += buildHTML(message)
        });
        //メッセージが入ったHTMLに、入れ物ごと追加
        $('.middle').append(insertHTML);
        $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
        $("#new_message")[0].reset();
        $(".form__submit").prop("disabled", false);
      }
    })
    .fail(function() {
      console.log('error');
    });
  };
  if (document.location.href.match(/\/groups\/\d+\/messages/)) {
    setInterval(reloadMessages, 7000);
  }
});
関連するhamlファイル
.messages
  .messages__message
    .messages__message__info
      .messages__message__info__member
        = message.user.name
      .messages__message__info__date
        = message.created_at.strftime("%Y年%m月%d日 %H時%M分")
    .messages__message__text
      - if message.content.present?
        %p.messages__message__text__content
          = message.content
      = image_tag message.image.url, class: 'lower-message__image' if message.image.present?

問題解決までの変更点は以下のとおり。
1. jsファイル、"buildHTML"内で定義されたhtmlにreturn html;を2箇所追記する。(エラーの解決にはこれだけでよかった気もする...)
2. hamlファイルから".message"のクラスを削除、hamlファイルとscssファイルをそれに合わせて調整する。
3. そのままでは自動更新された文にcssが当たらないので、"div class="messages__message" "の記述を削除する。(本来は閉じタグも消去しなければいけないが、記述ミスで上記コードには表記されていなかった)
4. .done内の".message"でクラス指定されている部分のクラスを指定し直す。

変更後のコードは以下

jsファイル
$(function(){
  var buildHTML = function(message){
    if (message.image){
      var html =  
        `<div class = "message" data-message-id=${message.id}>
          <div class="message__info">
            <div class="message__info__member">
              ${message.user_name}
            </div>
            <div class="message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="message__text">
            <p class="message__text__content">
              ${message.content}
            </p>
          </div>
          <img src=${message.image} >
        </div>`
        return html;
    } else {
      var html =
        `<div class = "message" data-message-id=${message.id}>
          <div class="message__info">
            <div class="message__info__member">
              ${message.user_name}
            </div>
            <div class="message__info__date">
              ${message.created_at}
            </div>
          </div>
          <div class="message__text">
            <p class="message__text__content">
              ${message.content}
            </p>
        </div>`
        return html;
    };
  }

    $('.new_message').on('submit', function(e){
    e.preventDefault();
    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);
      $('.middle').append(html);
      $('form')[0].reset();
      $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight},'fast');
      $('input').prop('disabled', false);
    })
    .fail(function(){
      alert('メッセージ送信に失敗しました');
    })
  })

  var reloadMessages = function() {
    //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
    last_message_id = $('.message:last').data("message-id");
    $.ajax({
      //ルーティングで設定した通りのURLを指定
      url: "api/messages",
      //ルーティングで設定した通りhttpメソッドをgetに指定
      type: 'get',
      dataType: 'json',
      //dataオプションでリクエストに値を含める
      data: {id: last_message_id}
    })
    .done(function(messages) {
      if (messages.length !== 0) {
        //追加するHTMLの入れ物を作る
        var insertHTML = '';
        //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
        $.each(messages, function(i, message) {
          insertHTML += buildHTML(message)
        });
        //メッセージが入ったHTMLに、入れ物ごと追加
        $('.middle').append(insertHTML);
        $('.middle').animate({ scrollTop: $('.middle')[0].scrollHeight});
        $("#new_message")[0].reset();
        $(".form__submit").prop("disabled", false);
      }
    })
    .fail(function() {
      console.log('error');
    });
  };
  if (document.location.href.match(/\/groups\/\d+\/messages/)) {
    setInterval(reloadMessages, 7000);
  }
});
hamlファイル
.message{data: {message: {id: message.id}}}
  .message__info
    .message__info__member
      = message.user.name
    .message__info__date
      = message.created_at.strftime("%Y年%m月%d日 %H時%M分")
  .message__text
    - if message.content.present?
      %p.message__text__content
        = message.content
    = image_tag message.image.url, class: 'lower-message__image' if message.image.present?
0
2
1

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
0
2