Matheus Bernardi
Matheus Bernardi

Reputation: 151

Calling a function that works synchronous in controller - Node

I'm working in a logic to pick it up the ID from an entity called "Group", i need set a variable from another entity, called User, with this value.

I created a function that search in mongo for an document with name "admin" and return his id. I think the problema is that the function is asynchronous, so, i only get this value later.

Here's what i trying to do:

function getAdminId() {
 Group.findOne(
  {
   name: "admin"
  },
  function(err, admin){
   if(err){
    console.log("Erro ao pegar o ID do admin");
   }else{
    return admin._id;
   }
  }
 )
};

The function that will create an user, but passing the value for the ID

exports.register = function(req, res, next) {

// Verifica se a chave digitada existe no banco de dados.
if (req.company) {
 var user = new User(req.body);
 var message = null;
 user.provider = "local";
 user.username = usernameGenerator.generateUsername("-");
 user.password = generator.generate({
  length: 8,
  numbers: true
 });
 user.name = "admin";

 // Pegar o id do grupo de admin
 user.groupid = getAdminId();
 console.log(user.groupid); // <--------- HERE'S WHERE IM TROUBLE

 // Chamar a função que envia o e-mail para o usuário.
 console.log("Usuário: " + user.username + " Senha: " + 
 user.password);

 user.save(function(err) {
  if (err) {
    message = getErrorMessage(err);
    req.flash("error", message);
    return res.redirect("/");
  } else {
    res.json({
      message: "Cadastrado."
    });
  }
 });
} else {
res.json({
  message: "Chave não encontrada."
});
}
};

How can i get the id value without blocking my processing?

The console.log(user.groupid) returns "undefined", probably because node call function and before the processment call console.log

Thank you

Upvotes: 2

Views: 263

Answers (1)

fardjad
fardjad

Reputation: 20404

Using callbacks is probably the most common way of doing async programming in JavaScript (and Node.js). However as of ES2017, one can use Promises in conjunction with async/await to write some non-blocking-async code which looks like synchronous code.

We can rewrite getAdminId function so it returns a promise instead of returning values in the callback (which doesn't work anyways because in CPS programming return values in callbacks don't matter):

function getAdminId() {
  return new Promise(function(resolve, reject) {
    Group.findOne({
        name: "admin"
      },
      function(err, admin) {
        if (err) {
          reject(new Error("Erro ao pegar o ID do admin"));
        } else {
          resolve(admin._id);
        }
      }
    );
  });
}

Then you can make your register middleware asynchronous and do something like:

 exports.register = async function (req, res, next) { // notice the async keyword
   // ...
   user.groupid = await getAdminId(); // notice the await keyword
   // ...
 };

Upvotes: 1

Related Questions