Je peux récupérer avec succès toutes les données stockées dans une collection appelée "topics" en utilisant find () avec le curseur et foreach. Cependant, lorsque j'essaie de définir les informations récupérées sur la variable d'appel "data" et de les renvoyer à la page, elle affiche toujours un tableau vide.
Comment puis-je résoudre ce problème?
app.get('/api/get_topics', (req, res)=>{ let data = []; MongoClient.connect(url, (err, db)=>{ const dbo = db.db('adoption'); let cursor = dbo.collection('topics').find(); cursor.forEach((el)=>{ const obj = { img : el.img, title : el.title, content : el.content } data.push(obj); }); db.close(); }); res.json(data); // [] ---> always empty res.end(); });
4 Réponses :
essayez ceci
app.get('/api/get_topics', (req, res)=>{ let data = []; MongoClient.connect(url, (err, db)=>{ const dbo = db.db('adoption'); let cursor = dbo.collection('topics').find(); cursor.forEach((el)=>{ const obj = { img : el.img, title : el.title, content : el.content } data.push(obj); }); db.close(); res.json(data); // [] ---> always empty res.end(); }); });
Vous devez renvoyer les données une fois votre connexion à la base de données établie.
Avant de fermer la connexion et après votre forEach
: parce que "forEach" est syncron et bloque la boucle d'événements
app.get('/api/get_topics', (req, res)=>{ let data = []; MongoClient.connect(url, (err, db)=>{ const dbo = db.db('adoption'); let cursor = dbo.collection('topics').find(); cursor.forEach((el)=>{ const obj = { img : el.img, title : el.title, content : el.content } data.push(obj); }); res.json(data); res.end(); db.close(); }); });
Remarque: vous devez créer une connexion globale et non pour chaque requête. Une connexion peut être réutilisée.
La raison des données
vides est que MongoClient.connect ()
est une fonction asynchrone, ce qui signifie que le code n'attend pas votre rappel pour pousser le contenu vers votre data
avant de définir les données de réponse.
Comme d'autres l'ont souligné, vous pouvez définir et terminer votre réponse dans votre rappel, mais je suis sceptique que cela fonctionnera. Une autre approche consisterait à utiliser un async / attendez la méthode
. Vous pouvez voir cette utilisation dans la documentation officielle de MongoDB a >.
De plus, je pense que vous pouvez omettre res.end ()
ou le déplacer vers la capture.
Par exemple:
app.get('/api/get_topics', (async (req, res) => { try { let data = []; const db = await MongoClient.connect(url); const dbo = db.db('adoption'); const cursor = dbo.collection('topics').find(); cursor.forEach((el)=>{ const obj = { img : el.img, title : el.title, content : el.content } data.push(obj); }); db.close(); res.json(data); } catch (err) { // Handle an error here... console.log(err); res.end(); } }));
MongoClient.connect (url, rappel)
...
Ce qui indique que le fnc connect () est une fonction asynchrone. D'où res.json (données); res.end (); sera exécuté avant que le rappel de la fonction de connexion ne soit appelé à l'endroit où vous remplissez votre tableau.
Je ne suis pas un programmeur de node.js, mais je crois que c'est une condition de concurrence. Le code appelle res.json (données) pendant que vous vous connectez et / ou effectuez une opération de recherche (asynchrone). Donc, fondamentalement, le thread principal est exécuté avant de lire vos documents.