Bonjour à tous,

J'ai un petit souci avec la porté des variables en NodeJS et plus précisement avec le contexte des fonctions.

Ce que je fais

Pour l'instant, j'ai 2 fichiers: login.js et user.js. Dans le premier, je gère la connexion tandis que le second sert à savoir si un utilisateur, avec les identifiants donnés, existe. J'ai essayé de gérer le problème avec une promesse, mais ça ne donne rien :/ Voici le code des 2 fichiers:
login.js

var userModel = require('../models/user');

[...]

exports.post = function (req, res) {
    let result = new Promise(function (resolve, reject){
        let tamp = userModel.login(req.body.loginValue, req.body.password);
        console.log("tamp = " + tamp);
        if (tamp.success){
            resolve({username: tamp.data.username, realname: tamp.data.realname})
        }
        else{
            reject(null);
        }
    });

    result.then(function(val){
        req.session.currentUser = { 
            username: val.username,
            realname: val.realname 
        };
        res.redirect('/');
    }, function(err){
        res.render('login', {
            layout: 'layouts/form',
            login: req.body.loginValue,
            errorMessage: result.errorMessage
        });
    }); 
}

user.js

[...]

exports.login = function (loginField, password) {
    var result = new Promise(function(resolve, reject){

        if (loginField == '' || password == '') {
            let errorMessage = 'Vous n\'avez pas complété tous les champs.';
            console.log("ERROR (null values)...");
            reject({ success: false, errorMessage: errorMessage });
        }

        let query = `SELECT username, realname FROM users 
                 WHERE username=? AND password=?
                 ALLOW FILTERING`;

        let values = [loginField, password];

        db.execute(query, values, function(err, results) {
        // Erreur : pas de personne trouvée, identifiants invalides.
        if (results.rowLength != 1) {
            console.log("ERROR (id)...");
            let errorMessage = 'Les identifiants sont invalides.';
            reject({ success: false, errorMessage: errorMessage });
        }

        // Succès : une personne trouvée, identifiants valides.
        console.log("SUCCESS!");
        resolve({ success: true, data: results.rows[0] });
        });

    });

    result.then(function(val){
        return val;
    }, function(err){
        return err;
    });
 }

Ce que je veux

Ce que j'aimerais, c'est que la variable tamp dans login.js ait la valeur que je renvoie dans user.js. J'ai testé mon code et la valeur que j'obtiens dans user.js est bonne (j'ai bien le pseudo et le nom de la personne).

Ce que j'obtiens

Mais le souci, c'est que que récupère la variable tamp dans login.js est undefined et tout plante :p De ce que j'ai lu, les fonctions sont exécutés dans un contexte propre à chaque fonction et ce serait ça la cause du problème. Est-ce que vous auriez une idée de comment résoudre ce problème ? Car j'ai un peu peur de devoir tout mettre dans une fonction et de me retrouver avec un code ignoble et illisible ^^'
Venant de Java, je n'ai pas eu l'habitude d'avoir des fonctions de callbacks. Donc si la solution est évidente, ne me tapez pas, s'il vous plait :p

4 réponses


PhiSyX
Réponse acceptée

Yop.

Retourne directement return result dans ta fonction login, tu devrais avoir un résultat dans ta variable tamp. (La promise)
Puis tu fais directement ton traitement .then((val) => { resolve(val.?) }, (err) => { reject(null) }) dans ta fonction post ?

MIRACLE ! Ca marche ! =D Merci beaucoup ^^

Mais j'ai une autre question alors: pourquoi ça marche ? Pourquoi je peux renvoyer une promise et pas une variable ?

Pourquoi ça te renvoyait undefined.
Tout simplement, lorsqu'on appelle une fonction et qu'on souhaite avoir un retour, il faut que cette fonction ait le mot clé return. Ca je pense que tu le sais.
Mais ton problème vient du fait que tu lorsque tu es dans une fonction anonyme/callback, le return est limité à sa fonction anonyme/callback.

En gros, ce tu faisais:

var a = function (b) { // Context 1
  if (b) {
    return 'cba'
  }

  ;(function () { // Context 2
    return 'cef' // limité à ce context 2)
  })()

  // Aucune instruction `return` pour ce context (1) - undefined.
}
console.log('Retour', a()) // undefined puisqu'aucune instruction return n'a défini.
console.log('Retour', a('ezfrzgz')) // 'cba'

Ce qu'il faut faire:

var a = function (b) { // Context 1
  if (b) {
    return 'cba'
  }

  return (function () { // Context 2
    return 'cef' // limité à ce context (2)
  })() // Une instruction `return` a été défini pour ce context 1. (Qui lui contient le résultat du context 2, dans cet exemple.) - 'cef'.
}
console.log('Retour', a()) // 'cef' puisqu'une instruction return a été défini.
console.log('Retour', a('ezfrzgz')) // 'cba'

Oh, je vois ! C'est vrai que maintenant que je vois un exemple simple et clair, je comprend mieux. Merci beaucoup ! =D
NB: Je vais garder le lien du topic dans mes favoris, je pense qu'il me sera encore utile x)