J'enregistre les offres favorites qu'un utilisateur «coeurs» dans mon application. Ces enregistrements incluent le propriétaire et les identifiants de l'offre. Je souhaite collecter les 25 meilleures offres favorites pour un utilisateur particulier. Toutes les commandes Firestore sont asynchrones et je dois collecter tous les objets d'offre avant de rendre la page.
C'est la première fois que j'utilise async / await et ce qui a commencé comme un est rapidement devenu async / attend imbriqué. Il doit y avoir un moyen plus simple de collecter les identifiants des objets fav, puis de rechercher les offres avec ces identifiants?
async getItems() { const collectfavs = async () => { favsRef = firestore.collection('favs').where('owner','==',getUserID()).orderBy('created', 'desc').limit(25); let allFavsSnapshot = await favsRef.get(); allFavsSnapshot.forEach(doc => { let data = doc.data(); favsList.push(data.offer); }); console.log('favs:',favsList); } const collectoffers = async () => { favsList.forEach(async (fav) => { let doc = await firestore.collection('offers').doc(fav).get() console.log('doc:', doc); let data = doc.data(); data.id = doc.id; offerList.push(data); }); console.log('offers:', offerList); } await collectfavs(); await collectoffers(); }
3 Réponses :
Je ne sais pas pourquoi vous définissez deux fonctions locales juste pour les appeler chacune une fois. Cela semble plus de code que nécessaire pour faire le travail. À part cela, ce que vous faites ne me semble pas très complexe. Mais si vous souhaitez réduire les lignes de code:
async getItems() { favsRef = firestore.collection('favs').where('owner','==',getUserID()).orderBy('created', 'desc').limit(25); let allFavsSnapshot = await favsRef.get(); allFavsSnapshot.forEach(doc => { let data = doc.data(); favsList.push(data.offer); }); console.log('favs:',favsList); favsList.forEach(async (fav) => { let doc = await firestore.collection('offers').doc(fav).get() console.log('doc:', doc); let data = doc.data(); data.id = doc.id; offerList.push(data); }); console.log('offers:', offerList); }
Gardez à l'esprit que je n'ai aucune idée de l'endroit où vous avez défini favsList
et offerList
, donc je l'utilise aveuglément de la même manière que vous l'avez montré.
Votre solution a imprimé des favs, des offres, des doc, des doc sur la console ... ce qui signifie que la offerList était vide lorsque je l'ai utilisée sur la page au lieu d'être remplie au préalable.
J'ai ajouté la solution qui consistait à écrire mon propre asyncForEach pour attendre que chaque promesse Firebase se termine. Rusé.
D'après ce que j'ai compris de votre commentaire à Doug Stevenson ci-dessus, vous voulez vous assurer que vos listes seront remplies avant de les utiliser. Pour ce faire, vous pouvez Promises a>. Ce que les promesses font, c'est nous donner un moyen de gérer l'asynchronisme dans le code de manière séquentielle.
Tout ce que vous avez à faire est de créer une promesse qui garantira que vous remplissez d'abord les listes que vous voulez, puis que vous les utilisiez.
Faites-moi savoir si cela vous aide.
Il semble que Firebase utilise beaucoup les promesses puisque chaque appel est asynchrone. Cela aide lorsque j'emboîte diverses fonctions firebase / firestore pour ajouter ou mettre à jour un objet de banque de données. Il semble également que dans JS, les gens se tournent davantage vers async / wait pour gérer les appels asynchrones. Dans ce cas, je voudrais utiliser async / await pour rassembler la liste des objets du magasin de données avant de rendre la page.
J'ai fini par avoir besoin de créer ma propre routine asyncForEach pour accueillir les appels async à Firebase à l'intérieur de la boucle. Merci à un article de Sébastien Chopin asyncForEach
await asyncForEach(favsList, async (fav) => { let doc = await firestore.collection('offers').doc(fav).get() let data = doc.data(); data.id = doc.id; offerList.push(data); });