【Vue】配列を取得してるのにlengthできない現象【Promise】
悪しきコード
export async function getAllData() { let buffData = []; // 1 const snapshot = await db.collection("comments").get().catch(() => { alert("エラーが発見されました"); }); // 2 snapshot.forEach(doc => { async function download() { // 3 let getData = await downloadImage(doc.data()).then(res => { return res }) buffData.push(getData); } download(); }) // 4 return buffData; }
自分もプログラムを書いている時には気づかなかったのですが・・・
非同期処理であるので実行順が1→2→4→3になるなぁと。
後、ページング処理で思いもよらない現象に陥りました。
以下の記事にて説明されている現象です。
「変な配列」が返ってきて、中身にデータが取得されているようで、mapやlengthが使えない現象。
→ 記事ではどうもPromiseオブジェクトが返ってきていたらしい。
でもasync関数が返しているPromiseオブジェクトの理由が正直よくわからない。
整理
一つの関数にasync/awaitを詰め込むのはよくないと考え、処理を分割しました。
export async function getAllData(limit, pagingToken) { let query = db.collection("comments").orderBy('createdAt', 'desc').limit(limit); const result = await query.get(); export async function downloadImageToBox(snapshot) { let buffData = []; for (let i = 0, len = snapshot.docs.length; i < len; ++i) { let data = snapshot.docs[i].data(); data.createdAt = dateCheck(data.createdAt); let getData = await downloadImage(data); buffData.push(getData); } return buffData } async function downloadImage(getData) { const imageURL = await storage.ref().child(getData.ID).getDownloadURL(); getData["downloadURL"] = imageURL; return getData; }
downloadImageToBox()では、for文を用いることで関数で定義したasync直下にawaitを置くことができました。
これでデータ取得→画像ダウンロード→表示の順序が守られました(果たしてこの順序が正しいのか?)。
mounted: async function() { let data = await getAllData(3, this.pagingToken); const buffData = await downloadImageToBox(data.BuffData); this.maps_data = buffData; this.pagingToken = data.nextPageToken; },
mount時の実行順です。関数を分割することで、以前よりもかなり可読性が増した気がします。
1関数内にasync/awaitを複雑に設置にすべきでないと学びました。