1

So I have this code

    User.prototype.save = function (fn){ //User is just an object
        var password = hashPassword(null, this.pswrd);

        var query=client.query('INSERT INTO myUser(usrnm,pswrd)VALUES($1,$2) ,[this.name,password], function(err, result) {
            if(err) {console.log(err)}
        });
        query.on("end", function (result) {client.end();});     
    }

and the hashPassword is

version 1

function hashPassword(salt,pass){
    var salt = salt?salt:new Buffer(crypto.randomBytes(128)).toString('hex');
    var pass = pass;
    var a=crypto.pbkdf2(pass, salt , 10000, 256, 'sha512',function(err, derivedKey) {
        return salt + (new Buffer(derivedKey).toString('hex')); 
    });
    return a;
}

I get a and password, undifined. I use return, so, why can just a take the value?

version 2

function hashPassword(salt,pass){
    var salt = salt?salt:new Buffer(crypto.randomBytes(128)).toString('hex');
    var pass = pass;
    crypto.pbkdf2(pass, salt , 10000, 256, 'sha512',function(err, derivedKey) {
        pass = salt + (new Buffer(derivedKey).toString('hex')); 
        console.log("pass in  > "+pass);
    });
    console.log("pass out  > "+pass);
    return pass;
}

I get pass in > fhjvoefvuhvuoedfv... (is hashed correctly), but pass out > undefined. Now, pass is global to hashPassword and I changed its value inside crypto, so why it does not keep it?

version 3

function hashPassword(salt,pass){
    var salt = salt?salt:new Buffer(crypto.randomBytes(128)).toString('hex');
    var pass = pass;
    var pass2;
    crypto.pbkdf2(pass, salt , 10000, 256, 'sha512',function(err, derivedKey) {
        pass2 = salt + (new Buffer(derivedKey).toString('hex'));    
        console.log("pass2 in  > "+pass2);
    });
    console.log("pass2 out  > "+pass2);
    return pass2;
}

So, I tried to fix the version2 problem by adding an extra var and I get pass2 in > fhjvoefvuhvuoedfv... (is hashed correctly), but pass2 out > undefined. How is this possible?

version 4

According to the first answer here I tried:

    var password ;
hashPassword(null, user.pswrd,function(p)
{
    password=p;
}
);

console.log("password  > "+password);

and

function hashPassword(salt,pass, fn){
    var salt = salt?salt:new Buffer(crypto.randomBytes(128)).toString('hex');
    var pass = pass;
    crypto.pbkdf2(pass, salt , 10000, 256, 'sha512',function(err, derivedKey) {
        fn(salt + (new Buffer(derivedKey).toString('hex')));    
    });
}

and password is undefined.

So, please, I tried and I tried and still nothing, please explain and show me what to do.

Thanks

Community
  • 1
  • 1
user2860857
  • 549
  • 3
  • 10
  • 21

1 Answers1

0

hashPassword is still an async function. You should use it like that:

var password ;
hashPassword(null, user.pswrd, function(p) {
    password=p;
    console.log("password  > "+password);
});

Do the rest of your work inside the callback (callback is the function you pass to another function to be called, read this). So, if you have a piece of code that need password to be initialized, place them inside the callback. That's the place that is going to be executed when password has its value.

Read this thread again and keep that in mind, your function is an async function as well.

When you have an async function somewhere in your function call chain, your whole task becomes async.

function f(callback) {
  function g() {
    function h() {
      function asyncFunction () {
        var returnValue = 'something';
        callback(returnValue);
      }
      asyncFunction()
    }
    h();
  }
  g();
}

When you have a callback function callback, and you are calling an async function and passing the callback to it, you should not expect your callback is going to be called before the rest of your code.

function f(callback) {
  var returnValue = 'something';
  // setTimeout is to just simulate an async function
  setTimeout(function () {
    callback(returnValue);
  }, 0)
}


console.log("first log")

f(function (data) {
  console.log("third log");
  console.log(data)
});

console.log("second log")

The order of logs in the above code kind of show you the order. The second log will be printed before the third log, as f is an async function, the callback function will be called later when the result is ready, while the rest of the code is being executed and not blocked for the fs result.

Community
  • 1
  • 1
Aᴍɪʀ
  • 7,623
  • 3
  • 38
  • 52
  • The code you suggest looks like my version 4. Can you be a little more specific? Also, I dont quite get this "Do the rest of your work inside the callback". What work and which callback? Thanks – user2860857 Dec 31 '15 at 20:00
  • @user2860857 I just updated my answer. Please feel free to ask if you have more question about this. – Aᴍɪʀ Dec 31 '15 at 20:09
  • So if I got it, you mean, continue all the work inside this `hashPassword(null, user.pswrd, function(p) { password=p; console.log("password > "+password); });` ? I updated my original question. Should I transfer the query inside the `hashPassword(null, user.pswrd, function(p) {....` ? Why can the query get the `password` value? Function scope? Is there a way to leave the code as is in my question and pass the value to the query? Thanks – user2860857 Dec 31 '15 at 20:50
  • @user2860857 That's nothing to do with function scope. You have to wrap your mind around whole javascript asynchronous functions and how they work. – Aᴍɪʀ Dec 31 '15 at 20:53