4

I'm using the bcryptjs package to hash and compare passwords.

The compareSync method used below is synchronous and returns a boolean. It is reliable and works as expected.

let trueOrFalse = bcrypt.compareSync('abcd', '1234');

if(trueOrFalse) {
    console.log('hooray, it was true');
} else {
    console.log('oops, it was false');
}

The next example uses the asynchronous compare method. I'm concerned that because this version is async if there is any delay on the server it may get to the if/else statement before bcrypt.compare has determined the value of res. Is this a valid concern or am I misunderstanding the nature of this type of async function?

let trueOrFalse;
bcrypt.compare('abcd', '1234', function(err, res) {
    trueOrFalse = res;
}

if(trueOrFalse) {
    console.log('hooray, it was true');
} else {
    console.log('oops, it was false');
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153

2 Answers2

6

Asynchronous method will be executed in parallel with your main program, so your console.log will be done before the callback function inside bcrypt.compare. You will see always 'oops, it was false'.

You can wait for the real result in your main function and then show something in console.

To make comparison 'waitable' you can wrap it into Promise:

function compareAsync(param1, param2) {
    return new Promise(function(resolve, reject) {
        bcrypt.compare(param1, param2, function(err, res) {
            if (err) {
                 reject(err);
            } else {
                 resolve(res);
            }
        });
    });
}

const res = await compareAsync(param1, param2);
console.log(res);

I prefer to wrap legacy callback functions into Promises because it will save an app from a callback hell.

exxbrain
  • 596
  • 4
  • 11
  • "*you should wait in your main thread*" - that's not possible. The proper mitigation of the problem is to defer the `console.log` to the future (when the async task has completed) by putting it inside the callback. – Bergi Oct 03 '19 at 18:42
  • Yes. You are completely right. But it could be more comfortable to use async/await syntax. So you will not appear in a callback hell at some moment ). – exxbrain Oct 03 '19 at 19:55
2

The Node.js runtime will surely run the synchronous code (the if-else statements) before you get the result from the async computation. You are guaranteed that the computation is completed only in the callback function:

bcrypt.compare('abcd', '1234', function(err, res) {
    // make your checks here
    if (res) {
      // ...
    }
})
Tsvetan Ganev
  • 8,246
  • 4
  • 26
  • 43