Approche de plusieurs requêtes MySQL avec Node.js

Je suis un débutant à la fois sur la programmation de style événement / rappel et NodeJS. J'essaie de mettre en place un petit serveur http qui sert des données ddbb en utilisant le module node-mysql.

Mes problèmes proviennent de la structuration des requêtes. Étant donné qu'il existe souvent des requêtes qui nécessitent des résultats de requêtes antérieures, je ne suis pas capable de les exécuter simultanément (de manière asynchrone) et je suis obligé d'attendre certains résultats.

Ma première approche était d'exécuter toutes les requêtes non dépendantes en même temps et ensuite de boucler jusqu'à ce que tous aient mis un drapeau en disant que je suis terminé afin que je puisse continuer avec les dépendants (synchronisés), mais je ne le fais pas Savoir si c'est la bonne approche.

Quelque chose comme ça:

function x(){ var result_for_asynch_query_1 = null var result_for_asynch_query_2 = null mainLoop(){ // call non-dependant query 1 // call non-dependant query 2 // loop until vars are != null // continue with queries that require data from the first ones } } //for each browser request httpServer{ call_to_x(); }.listen(); 

De cette façon, je peux gagner du temps dans le résultat final, car je n'attends pas toutes les réponses de manière sérieuse, mais juste pour la plus longue.

Existe-t-il un moyen commun de le faire? Tout modèle de conception que je ne suis pas en train de suivre?

Essayez de penser autrement (il y a une bonne introduction sur le flux asynchimique howtonode.org )

 var db = get_link_or_pool(); do_queries( callback ) { db.query(sql1, function(err, res1) { if (err) { callback(err); return; } // use res1 ... db.query(sql2, function(err, res2) { if (err) { callback(err); return; } callback(null, res2); // think 'return' } }); } request_handler(req) { do_queries( function(err, result) { if(err) report_error(err); else write_result(req, result); }); } 

Il faut éviter la pyramide de la fatalité:

 var express = require('express'); var Q = require('Q'); var app = express(); app.get('/',function(req,res){ var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : '' }); connection.connect(); function doQuery1(){ var defered = Q.defer(); connection.query('SELECT 1 AS solution',defered.makeNodeResolver()); return defered.promise; } function doQuery2(){ var defered = Q.defer(); connection.query('SELECT 2 AS solution',defered.makeNodeResolver()); return defered.promise; } Q.all([doQuery1(),doQuery2()]).then(function(results){ res.send(JSON.stringify(results[0][0][0].solution+results[1][0][0].solution)); // Hint : your third query would go here }); connection.end(); }); app.listen(80); console.log('Listening on port 80'); 

Cet échantillon montre un résultat qui dépend de 2 valeurs calculées indépendantes. Chacune de ces valeurs a été interrogée dans doQuery1 et doQuery2. Ils sont exécutés en séquence, mais de manière asynchrone.

Ensuite, vous pouvez voir Q.all(... qui appelle essentiellement le rappel "alors" en cas de succès. Dans ce rappel, le calcul est terminé.

En utilisant les promesses (détails: Github Q: promesse pour Javascript et wikipedia ) permettent de rendre votre code plus propre, de calculer séparément et de gérer les résultats et de bouger les choses autour.

Regardez à quel point il serait facile d'ajouter "doQuery3" comme pré-requis pour votre calcul!

Et ci-dessous, le "package.json" s'affiche dans l'exemple de code:

 { "name": "hello-world", "description": "hello world test app", "version": "0.0.1", "private": true, "dependencies": { "express": "3.2.0", "q": "0.9.3", "mysql":"2.0.0-alpha7" } } 

Une autre solution consiste à concaténer toutes les déclarations, en terminant chacune avec un point-virgule. Par exemple, pour sélectionner parmi plusieurs tables, vous pouvez utiliser cette requête:

var sql = 'select * from user; select * from admin;'

Ensuite, vous pouvez utiliser une seule connexion pour exécuter les instructions multiples:

var connection = mysql.createConnection({multipleStatements: true}) connection.query(sql)

Remarque: plusieurs instructions sont désactivées par défaut pour empêcher l'injection SQL. Assurez-vous d'échapper correctement à toutes les valeurs (voir docs) .

J'ai trouvé ce qui précède très utile pour résoudre ce problème:

Tiré de http://book.mixu.net/node/ch7.html – Beaucoup d'autres excellents exemples ici!

 function async(arg, callback) { console.log('do something with \''+arg+'\', return 1 sec later'); //replace setTimeout with database query setTimeout(function() { callback(arg * 2); }, 1000); } // Final task (return data / perform further operations) function final() { console.log('Done', results); } // A simple async series: var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function series(item) { if(item) { async( item, function(result) { results.push(result); return series(items.shift()); }); } else { return final(); } } series(items.shift()); 

"Prenez un ensemble d'éléments et appelez la fonction de flux de contrôle de la série avec le premier élément. La série lance une opération asynchrone () et lui transmet un rappel. Le rappel renvoie le résultat dans le tableau des résultats, puis appelle série avec le prochain Élément dans le tableau des éléments. Lorsque le tableau des éléments est vide, nous appelons la fonction finale (). " (À partir de http://book.mixu.net/node/ch7.html )