
無限スクロールを作っていますが、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

await が抜けてるところがあるのでは?
catch(err => {}) でエラーが握りつぶされてるかも?
ちなみにfetchはXMLHttpRequestではないのでajaxと呼ぶべきかどうかは判断が分かれます
SurferOnWwwさん
どこかが非同期処理になってしまっているようですね
hoshi-takanoriさん
その中でconsole.log(err)したら「TypeError: Cannot read properties of undefined (reading 'user_id')」と返ってきました
yambejpさん
ありがとうございます。
int32_t さんの回答にある通り、ループの終了条件がおかしいために無限ループになり、data.comments の個数よりも i が大きくなると data.comments[i] が undefined なので user_id にアクセスできなくてエラーになってるのでしょうね。が、表示漏れの原因はそれではなく、非同期で結果が返ってくる順番の問題だと思います。
ちなみに、user や article を一つ一つ分けて取得するのは効率が悪いので、API を修正できるなら getSidebarComment でまとめて返すようにした方がいい気がします。
hoshi-takanori
ありがとうございます。getSidebarCommentで全て取得したら思い通りの処理を実現できました

回答3件
あなたの回答
tips
プレビュー