質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

312閲覧

[ajax通信]なぜか正しく動いてしまうJSコードの解明

yu-smc

総合スコア610

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2018/06/27 07:34

編集2018/06/27 07:59

[なにをやったか]
チャットサービスで、5秒おきに非同期通信でメッセージを更新する処理を実装しています。
正しく動いてくれるのはいいですが、それがどうにも不可解でもやもやしているので、
JSに慣れている方に見ていただきたく投稿しました。

以下JSコードです。

js

1 var id = $('.messages .message:last-child').data('messageId'); //1 2 var interval = setInterval(function(){ //2 3 var insertHTML = ''; 4 if (window.location.href.match(//groups/\d+/messages/)) { 5 $.ajax({ 6 url: location.href, 7 dataType: 'json', 8 }) 9 .done(function(data){ 10 data.forEach(function(message){ //3 11 if (message.id > id) { 12 console.log(id) 13 console.log(message.id) 14 insertHTML += buildHTML(message); 15 } 16 }); 17 $('.messages').append(insertHTML); 18 scrollToNewest(); 19 }) 20 .fail(function(data){ 21 alert('自動更新できません。更新するにはページを再度読み込んでください。'); 22 }); 23 } else { 24 clearInterval(interval); 25 } 26 id = $('.messages .message:last-child').data('messageId'); 27 }, 5000);

大まかな流れです。
1 ブラウザロード時に表示されているメッセージの中から、HTMLで付与したdata-message-idが最大のものを取得。
2 0.5秒間隔でajaxを発動
3 DBから取得してきたメッセージ全てを検証し、1で取得した最新idより大きい場合はHTMLに追加する

[前提]
投稿自体もajaxで処理し、投稿ボタンを押した瞬間にHTML描画するようにしています。
同時にDBにも保存をしています。

また、idをsetIntervalの外側と終了時に二回取得しているのは、setIntervalの開始直後に取得すると、5秒間に複数投稿があった場合いくつかの投稿が取得できない問題に対処するためです。

[疑問]
この処理では、投稿時にajax処理されたHTMLと、非同期通信時に処理されたHTMLの、2つ同じ投稿がダブって表示されてしまうのではないかと思いました。しかし実際は自分の投稿時は1回のみ表示され、その間に他アカウントから投稿があっても正しく表示されます。

なぜこれで正しく動くことになるのでしょうか。。。プログラムって難しい
というわけで、ぜひご教授いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2018/06/27 07:37

コードブロックの冒頭を```xxx のようにxxx部分に言語名記載すると言語にあわせて適切にハイライトしてくれるのでブロックの中に補足を書く必要はありません。 使える言語一覧→https://teratail.com/questions/7119
yu-smc

2018/06/27 07:45

言語指定がうまくできていませんでした。ご指摘ありがとうございます!
m.ts10806

2018/06/27 07:55

ajaxですがlocation.href と自身を指定しているのはどうしてでしょうか?別途取得用のみのプログラムを設置した方が良いように思うのですが
x_x

2018/06/27 08:14

投稿時には、サーバー通信前に描画しているということでしょうか?
yu-smc

2018/06/27 08:19

mts10806さん > https://qiita.com/yuki-n/items/885f6f059167a7b5aedc こちらを参考にしました。今回はアプリケーションが小規模なのでこれでもよいかなといった次第です。もし別途プログラムを設置することが強く必要であれば理由を教えていただけるととてもありがたいです。。
yu-smc

2018/06/27 08:19

x_xさん> そうです!なにか不備でしょうか?
x_x

2018/06/27 08:43

messageIdが最大をとるということは連番だと思うのですが、ローカルではつけられません。投稿時の自分のメッセージ表示にはmessageIdはついてないということですよね?
yu-smc

2018/06/28 02:18

自分のメッセージを表示する際もDBからidをとってきてそれをmessageIdにしています。
x_x

2018/06/28 03:29

それはサーバー通信後ですよね? サーバー通信前に描画しているという話ではないのでしょうか?
guest

回答1

0

ベストアンサー

2 0.5秒間隔でajaxを発動

↑5秒間隔です。

id = $('.messages .message:last-child').data('messageId'); }, 5000);

↑ここでidを取得しているのは、「5秒間隔のajax通信処理開始直後に最大のidを再取得する」のが目的です。

ajax通信自体は非同期で実行されるので、id再取得後に通信終了後処理(doneの中身)が実行される形になります。

投稿2018/06/27 07:42

tkturbo

総合スコア5572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu-smc

2018/06/27 07:53

なるほど! なぜif文の外でidを再取得しているのにajax通信開始直後になるのでしょうか?
tkturbo

2018/06/27 08:01

通信開始(非同期開始)+→通信中(非同期)→終わったらdone            +→id再取得 ↑ajaxの処理が本体処理に対して非同期(ソースコード上の記述位置は処理開始のトリガにすぎず、処理開始の次には以降の行で記述されている処理が順次実行されていく)だからこういう風になるのです。
yu-smc

2018/06/27 08:05

そういうことなのですね、、!知識不足で概念がまだ完璧にはつかめませんが、なんとなくは理解できました。 ご丁寧にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問