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

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

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

Q&A

解決済

3回答

987閲覧

ajaxで取得したデータを全て表示できない

suika11

総合スコア166

0グッド

1クリップ

投稿2022/04/13 01:52

編集2022/04/13 03:28

無限スクロールを作っていますが、ajaxで取得したデータを元に要素を生成したいのですが、毎回1つか2つ生成されず抜けがあります。データは全てサーバーから取得できているためjs内に問題があります。

追記
TypeError: Cannot read properties of undefined (reading 'user_id')とエラーを吐きました。「 this.AjaxCommentUser(data.comments[i].user_id)」が問題の箇所ですが、data.commentsの各オブジェクト内にuser_idはあるのでなぜこのようなエラーを返すのかわかりません

該当のソースコード

index.blade.php

1 methods: { 2 AjaxAddContent() { 3 if (!this.itemLoading) { //読み込み中は読み込めないようにする 4 this.itemLoading = true 5 // 追加コンテンツ 6 fetch('/ajax/getSidebarComment', { 7 method: 'POST', 8 body: new URLSearchParams({ 9 count: this.page 10 }), 11 headers: { 12 'X-CSRF-TOKEN': gid("jsHandOvers").dataset.csrf 13 }, 14 }).then(res => { 15 return res.json(); 16 }).then(data => { 17 // console.log(data.comments.length) 18 let AddContent = ""; 19 for (let i = 0; data.comments; i++) { 20 this.AjaxCommentUser(data.comments[i].user_id) 21 .then(user => { 22 this.AjaxCommentArticle(data.comments[i].article_id) 23 .then(article => { 24↓ここで要素を作るがなぜか抜けがある 25 AddContent += 26 `<div class="streamTile"><div><a href="/articles/${data.comments[i].article_id}?id=${data.comments[i].id}"></a><div class="userInfo"><a href="/users/${user.userID}"><div class="userIcon"><img src="/storage/${user.icon || 'icon/initial.jpeg'}" class="icon"></div><div><div class="userName _ellipsised">${user.name || '氏名'}</div><div class="userID">@${user.userID}</div></div></a><div class="commentDate">${data.comments[i].updated_at}</div></div><div class="commentArea"><div class="comment _ellipsised">${data.comments[i].body || ''}</div></div><div class="titleArea"><div class="title _ellipsised">${article.title}</div></div></div></div><div class="tileSeparator"></div>`; 27 if (data.comments.length - 1 === i) { 28 $('#timelineContainer').append(AddContent); 29 this.page += data.comments.length 30 } 31 }).catch(err => {}); 32 }).catch(err => {}); 33 } 34 }).catch(err => { 35 // console.log(err.response) 36 this.itemLoading = false 37 }).finally(hoge => { 38 this.itemLoading = false 39 }); 40 } 41 }, 42 async AjaxCommentUser(user_id) { 43 let res = await fetch(`/ajax/users/${user_id}`, { 44 method: 'POST', 45 headers: { 46 'X-CSRF-TOKEN': gid("jsHandOvers").dataset.csrf 47 }, 48 }); 49 let data = await res.json(); 50 return data.user; 51 }, 52 async AjaxCommentArticle(article_id) { 53 let res = await fetch(`/ajax/articles/${article_id}`, { 54 method: 'POST', 55 headers: { 56 'X-CSRF-TOKEN': gid("jsHandOvers").dataset.csrf 57 }, 58 }); 59 let data = await res.json(); 60 return data.article; 61 }, 62 } 63 }).mount("#timelineContainer"); 64 65

試したこと

「ajax 全て表示」等で検索

補足情報(FW/ツールのバージョンなど)

PHP 8.1.1
Laravel 8.79.0

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2022/04/13 01:58

await が抜けてるところがあるのでは?
hoshi-takanori

2022/04/13 02:02

catch(err => {}) でエラーが握りつぶされてるかも?
yambejp

2022/04/13 02:21

ちなみにfetchはXMLHttpRequestではないのでajaxと呼ぶべきかどうかは判断が分かれます
suika11

2022/04/13 03:45

SurferOnWwwさん どこかが非同期処理になってしまっているようですね hoshi-takanoriさん その中でconsole.log(err)したら「TypeError: Cannot read properties of undefined (reading 'user_id')」と返ってきました yambejpさん ありがとうございます。
hoshi-takanori

2022/04/13 06:55

int32_t さんの回答にある通り、ループの終了条件がおかしいために無限ループになり、data.comments の個数よりも i が大きくなると data.comments[i] が undefined なので user_id にアクセスできなくてエラーになってるのでしょうね。が、表示漏れの原因はそれではなく、非同期で結果が返ってくる順番の問題だと思います。 ちなみに、user や article を一つ一つ分けて取得するのは効率が悪いので、API を修正できるなら getSidebarComment でまとめて返すようにした方がいい気がします。
suika11

2022/04/14 22:36

hoshi-takanori ありがとうございます。getSidebarCommentで全て取得したら思い通りの処理を実現できました
guest

回答3

0

fetchはpostのデータ私はformdataが基本ですが認識はあっていますか?
切り分けが必要。fetch().then(res=>res.json()).then(console.log)で想定したデータが取れるか確認します。受け取れてなければfetchの問題、受け取れていて表示がおかしいならその後の処理の問題

投稿2022/04/13 02:13

yambejp

総合スコア114829

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

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

suika11

2022/04/13 02:50

for文の直前の段階では想定データは取得できていました。なのでfor文の中に問題があると睨んでいます
yambejp

2022/04/13 02:59

そうなるともうfetchはおいておいて、特定の配列から一定の表示をすることに集中してください
guest

0

js

1 for (let i = 0; data.comments; i++) {

(ループ終了条件がおかしいですがそれは本題ではありません)
このループで data.comments に対して一斉に非同期処理を開始していますが、

js

1 if (data.comments.length - 1 === i) { 2 $('#timelineContainer').append(AddContent);

このコードが呼ばれるのが data.comments の順番どおりとは限らないため、この条件を満たした後の非同期処理の結果が捨てられているようにみえます。

ループの中で await して data.comments の順番どおりに非同期処理の結果を処理をするか、Promise.all() ですべての非同期処理が完了するのを待ってから AddContent を画面に出すべきでしょう。

投稿2022/04/13 04:03

編集2022/04/13 05:07
int32_t

総合スコア20872

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

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

0

自己解決

getSidebarCommentの一度でデータを取得したら全ての要素を表示できました

投稿2022/04/14 22:37

suika11

総合スコア166

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問