Tout d'abord, je suis désolé si cette question a déjà une réponse, mais j'ai recherché ce genre de question et je n'ai rien trouvé d'utile.
Je développe une application NodeJS qui utilise le package mysql npm pour interroger une base de données. J'ai écrit plusieurs requêtes qui fonctionnent correctement à l'aide de promesses (car c'est ainsi que fonctionne le module SQL). Je n'ai aucun problème lorsque la fonction de procédure de requête get_works
(définie ci-dessous) est appelée normalement.
Cependant, lorsque j'appelle cette fonction procédurale dans Express Router, j'obtiens un comportement étrange.
view.get("/works", (req, res) => { (async () => { res.json(await get_works()); })() }); async function get_works(offset=0,limit=6){ let cdc_database = mysql.createConnection({ /*Filled with credentials*/ }); const get_texts = `SELECT TEXID,TXNOM,TXRES FROM TEXTE LIMIT ${limit} OFFSET ${offset};`; // Valid request /*Two steps: get texts and get authors of each texts*/ cdc_database.connect(); const texts = await database_promise_query(cdc_database, get_texts); /*This await always have a correct output*/ let text_authors = []; for(i = 0; i < texts.length; i++){ get_text_authors = `SELECT AUPRE, AUNOM FROM AUTEURS,ECRIT_PAR\ WHERE AUTEURS.AUTID=ECRIT_PAR.AUTID AND TEXID=${texts[i].TEXID};`; // Request is valid text_authors[i] = (await database_promise_query(cdc_database, get_text_authors)); /* ^^^^^^^^ The await above returns an undefined value randomly when called through the router */ if(text_authors[i] === undefined){ console.error(`[get_works] - Server error on ${i}th text's authors`) text_authors[i] = [{AUPRE: "Prénom", AUNOM: "Nom"}] } } cdc_database.end(); return works_to_JSON(texts, text_authors) }
Parfois, une requête adressée à la base de données n'aura pas de valeurs indéfinies, mais une fois qu'il y aura une valeur indéfinie, toutes les valeurs suivantes seront également indéfinies.
Example trace log (1st call, 3 errors) [ [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], [ { AUPRE: 'Prénom', AUNOM: 'Nom' } ], [ { AUPRE: 'Prénom', AUNOM: 'Nom' } ], [ { AUPRE: 'Prénom', AUNOM: 'Nom' } ] ] (2nd call, no error) [ [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ], [ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ], ]
Voici l'emballage de ma promesse :
function database_promise_query(database, query){ return new Promise(res => { database.query(query, (error, results, fields) => { if(error) {res(undefined); console.log(error)} res(results); }) }) }
Cependant, appeler cette fonction en dehors du routeur comme ceci fonctionne parfaitement :
(async () => { await get_works(0, 10); await get_works(10, 10); await get_works(20, 10); await get_works(30, 10); })()
Est-ce que j'ai raté quelque chose ? Je pense que toutes les requêtes sont correctes car je peux obtenir les résultats souhaités, le problème peut provenir de ma gestion asynchrone/attente. Merci pour toute l'aide que vous pouvez apporter.
Sur la base de la suggestion de @tromgy, j'ai réécrit le wrapper de la promesse.
function database_promise_query(database, query){ return new Promise((res, rej) => { database.query(query, (error, results, fields) => { if(error) {rej(error); throw new Error(error)} console.log("Received response", results) res(results); }) }) }
Cependant, le rejet jamais ne se produit (ce qui est raisonnable puisqu'il n'y a aucune donnée correspondante dans la base de données). Pour nettoyer les journaux, j'ai désactivé un autre routeur pour des requêtes similaires utilisant une connexion à la base de données différente. La suppression de ce routeur a également résolu le bug. Je ne sais pas comment cela est possible (peut-être qu'une variable est déclarée globale, donc je chercherais ce genre de problème).
Comme le montre l'image, le problème est un compteur de boucles partagé. Un de mes collègues a oublié d'ajouter le mot-clé
let
avant d'itérer, donc la boucle for a sauté les valeurs.Je déteste cette fonctionnalité JavaScript en ce moment. Merci pour l'aide!