IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

NodeJS Discussion :

Résultat undefined sur requête


Sujet :

NodeJS

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 189
    Par défaut Résultat undefined sur requête
    Bonjour à tous,

    Je débute avec nodeJS, je bloque sur un truc qui doit être tout c.. mais je ne comprend pas

    Dans une route :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    app.get('/bieres/', bieres.index);
    Dans le controller correspondant j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    exports.index = function(req, res) {
    	res.render('inc_bieresListing.jade', {params: {categorie: getCategories() }});
    }
     
    var getCategories = function() {
    	console.log('ici1');
    	var temp='';
    	sql.query(mysql.format(req_boissoncategorie_sel1)).done(function (r) {
    		for (i = 0; i < r.length; i++) {
    			temp += i + " ";
    			console.log('ici2');
    		}
    		console.log('ici2');
    		return temp;
    	});
    	console.log('ici3');
    }
    Dans les logs, j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ici1
    ici3
    GET /bieres/ ...
    ici2
    ici2
    ici2
    ici2
    GET /css/font....
    Je comprend que la fonction getCategories est bien appelé, que les instructions sont appelées dans l'ordre et le résultat correspondant à la rapidité d'exécution de chaque instruction.

    Dans jade :
    l'affichage de me donne '[object Object]'
    l'affichage de me donne 'undefined'


    Cela veux dire que la page est affichée avant d'avoir le résultat d'appel de getCategories ?

  2. #2
    Membre émérite
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Billets dans le blog
    1
    Par défaut
    Tout à fait!

    En node.js, les entrées/sorties (I/O) (les appels en base de données, la lecture/écriture de fichier, ...) sont asynchrones. Ceci afin de ne pas faire attendre les autres requêtes tout en ne multipliant pas les processus (comme en PHP par exemple) et en optimisant donc l'utilisation processeur.

    Comme tu rends ton template jade dans le même flux synchrone que l'appelle de ta requête, le retour n'existe pas quand tu commences à rendre. A ce moment là, en fait, ta requête a à peine commencée a récupérer tes catégories (dans un processus asynchrone distinct). Il faut que tu mettes le render dans la callback de ta requête SQL, callback qui est appelée avec, en argument, la liste de tes catégories et au moment où le processus asynchrone a fini de les récupérer donc. Cela donne un code comme celui-ci a peu près (en reprenant ce que tu as fait au maximum, ce qui veut dire que les nommages sont certainement à revoir):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    exports.index = function(req, res) {
    	getCategories(res);
    }
     
    var getCategories = function(res) {
    	console.log('ici1');
    	var temp='';
    	sql.query(mysql.format(req_boissoncategorie_sel1)).done(function (r) {
    		for (i = 0; i < r.length; i++) {
    			temp += i + " ";
    			console.log('ici2');
    		}
    		console.log('ici2');
     
                    res.render('inc_bieresListing.jade', {params: {categorie: temp}});
    	});
    	console.log('ici3');
    }
    N'hésite pas à me dire si je n'ai pas été clair!

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 189
    Par défaut
    Impec

    Merci

  4. #4
    Membre émérite
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Billets dans le blog
    1
    Par défaut
    Pas de problème!

    A noter, pour aller plus loin, que ce pattern de callback n'est pas le seul à traiter cette problématique de l'asynchronicité. On peut y ajouter les promises ainsi que les générateurs et itérateurs en ES6.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 189
    Par défaut
    Je me permet de revenir vers toi, je pense avoir bien compris le système "d'asynchronisité" des exécutions, mais je ne voie pas comment adapter le code en fonction. Par exemple, ci-dessous un début de code de vérif de formulaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    	name = req.body.nom.trim();
    	fournisseur = req.body.fournisseur.trim();
    	idCategorie = parseInt(req.body.categorie) || 0;
     
    	var error = [];
    	if (!name) 
    		error.push({'message':'Le nom de la boisson est obligatoire.'});
    	else {
    		sql.query(mysql.format(req_boissons_sel2, name)).done(function (r) {
    			if (Object.keys(r).length > 0) error.push({'message': 'Cette boisson existe déjà.'});
    			console.log(1);
    		});
    	}
    	if (fournisseur) {
    		sql.query(mysql.format(req_brasseries_sel1, fournisseur)).done(function (r) {
    			if (Object.keys(r).length > 0) error.push({'message': 'Cette boisson existe déjà.'});
    			console.log(1);
    		});		
    	}
    	if (idCategorie == 0) error.push({'message': 'La catégorie est obligatoire.'});
    	if (req.file) {
    		var file =  req.file;
    		if(file.size > 3000000) error.push({'message':'La taille maximale du logo est 3M.'});
    		if(file.mimetype !== 'image/png' && file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/svg+xml') error.push({'message':'Les formats de logo supportés sont  jpeg, jpg, svg et png.'});
    	}
     
    	console.log(2);
     
    	if (Object.keys(error).length > 0 ) {
    		if (req.file) fs.unlinkSync(req.file.destination + req.file.filename);
    		res.setHeader('Content-Type', 'application/json');
    		console.log(JSON.stringify({"error": error}));
        	res.send(JSON.stringify({"error": error}));
    		return;
    	}
    Les logs de la console le renvoient :
    2
    {"error":[{"message":"La catégorie est obligatoire."}]}
    POST /boissons/ 200 17.053 ms - 56
    1

    Je comprend que le script vérifie le name :
    - si pas présent => log un message d'erreur
    - si présent, je vérifie que le name n'éxiste pas dans la base. Ce proccess prenant un temps d’exécution, le script poursuit l’exécution des lignes suivantes. ...
    Bref le résultat est renvoyé alors que la partie liée à la bdd n'est pas achevée.

    J'ai donc pensé à découpé le code en différente fonction pour les "promisées". Mais il faudrait donc que je découpe le script en 36 morceaux ? C-A-D :
    - 1 pour la verif du name
    - 1 pour la verif de la categorie
    - 1 pour la vérif de l'image

    ...etc

  6. #6
    Membre émérite
    Avatar de Gnuum
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mars 2007
    Messages
    215
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2007
    Messages : 215
    Billets dans le blog
    1
    Par défaut
    En fait, le moyen le plus rapide mais qui va rendre ton code moche et qui n'est pas performant, c'est d'empiler les callbacks les unes dans les autres.
    En gros, un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function checkName() {
        executeSQLRequest(requestCheckName, function checkCategory() {
            executeSQLRequest(requestCheckCategory, function checkProvider() {
                executeSQLRequest(requestCheckProvider, function() {
                    res.send();
                });
            });
        });
    }
    Ce code n'est pas évolutif (défaut de factorisation), deviendra rapidement difficile à maintenir et n'est pas performant car chaque requête attend que celle d'avant soit terminée.

    En fait, ce que tu voudrais c'est exécuter ces 3 requêtes en parallèle (c'est un des principaux intérêts de gérer les I/O en asynchrone), puis exécuter un callback quand tu as tous les résultats.
    Or, ce n'est pas trivial du tout à coder soi-même!
    La plupart des gens utilisent la bibliothèque async.js pour faire ce genre de choses.

    Si tu as envie d'être aidé un peu plus dans ton développement node.js et notamment la gestion de l'asynchronicité, je peux te suggérer de jeter un coup d'oeil à mon framework Danf qui aide beaucoup à gérer ça simplement (il découple ton code métier de ta gestion de séquence synchrone/asynchrone notamment). Voici un lien vers un tutoriel en français qui explique globalement le concept.
    Je suis à ta disposition si tu as des questions sur le framework bien sûr et/ou pour te guider dans l'adaptation de ton code avec le framework pour que tu vois ce que ça peut donner.

Discussions similaires

  1. [Débutant] problème de compréhension
    Par Sylvester dans le forum Général Java
    Réponses: 18
    Dernier message: 21/07/2005, 09h16
  2. Réponses: 5
    Dernier message: 11/04/2005, 10h21
  3. [C#] Problème de compréhension de System.Convert ET Provider
    Par papouAlain dans le forum Windows Forms
    Réponses: 5
    Dernier message: 18/11/2004, 21h52
  4. onclipevent (problème de compréhension)
    Par stephane eyskens dans le forum Flash
    Réponses: 8
    Dernier message: 24/09/2003, 15h09
  5. Problème de compréhension des ensembles
    Par Cornell dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 22h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo