2012-03-16 4 views
2

Pour des raisons d'organisation, je sépare mon code source en modules, par exemple j'ai le module user sur mon application node.js qui est responsable de la récupération des informations utilisateur à partir d'une base de données MongoDB. Je fais quelque chose comme ceci:Rappel à MongoDB Opération avec Node.js

var mongo = require("mongodb"), 
    Server = mongo.Server, 
    Db = mongo.Db; 

var server = new Server("localhost", 27017, { auto_reconnect: true }); 
var db = new Db("users", server); 

module.exports = { 
    login: function(user, pass, callback) { 
     var reg_result = null; 

     db.open(function (err, db) { 
      if(!err) { 
       db.collection("users", function(err, collection) { 
        collection.findOne(
         { 
          "username": user, 
          "password": pass 
         }, 
         function(err, item) { 
          if(!err) { 
           reg_result = item; 
          } else { 
           reg_result = "error"; 
          } 
         } 
        ); 
       }); 
      } else { 
       reg_result = "error"; 
       console.log("ERROR: " + err); 
      } 
     }); 

     callback(reg_result); 
    } 
} 

et l'exécution sur mon script de test comme celui-ci:

var user = require("./user.js"); 

user.log("test", "test", function(msg) { 
    console.log(msg); 
}); 

Il fait l'opération de base de données et récupère la valeur, mais chaque fois qu'il retourne seulement null, Lorsque je n'initialise pas la variable reg_result, elle renvoie undefined. Que dois-je faire pour corriger cela?

Je débogué en utilisant console.log sur le user.js et le item a été émis, mais je veux avoir le rappel que je peux utiliser l'élément sur d'autres sources, comme mon script de test

Répondre

5

Vous appelez la fonction de rappel tout de suite, mais aller à la DB prend du temps et est donc fait de manière asynchrone. À la place, appelez votre rappel à l'heure appropriée en utilisant l'argument résultat de la fonction transmise en tant que dernier paramètre à la fonction .findOne(). Le rappel devrait obtenir un argument d'erreur et un argument de résultat:

login: function(user, pass, callback) { 
    db.open(function (err, db) { 
     if(!err) { 
      db.collection("users", function(err, collection) { 
       collection.findOne(
        { 
         "username": user, 
         "password": pass 
        }, 
        function(err, item) { 
         if(!err) { 
          callback(null,item); 
         } else { 
          callback("error"); 
         } 
        } 
       ); 
      }); 
     } else { 
      callback("error",null); 
     } 
    }); 
} 


user.login("test", "test", function(err,msg) { 
    if(err) { 
     //error occured above; 
    } else { 
     //success 
     console.log(msg); 
    } 
}); 

cela est tout simplement en tirant le même modèle à travers le mongodb-conducteur utilise. espérons que ça aide.

+0

Merci beaucoup, cela fonctionne parfaitement! Je passe d'applications mobiles jQuery à l'aide de Phonegap à node.js, donc il est parfois difficile de s'habituer au nœud asynchrone. **:) ** –