Promisifying bcrypt-nodejs with Bluebird

I'm using NodeJS, with bcrypt-nodejs (https://github.com/shaneGirish/bcrypt-nodejs) and Bluebird for promises. Came up with this code and been wondering if there is better way to do the same thing. I have module with:

var Promise = require("bluebird"),
	bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));

// ....[some othe code here]

	Users.prototype.setPassword = function(user) {

		return bcrypt.genSaltAsync(10).then(function(result) {
			return bcrypt.hashAsync(user.password, result);
		});

	};

then from another module I call users.setPassword as below:

app.post('/api/v1/users/set-password', function(req, res, next) {
	users.setPassword(req.body).then(function(result) {

		// Store hash in your password DB.
		console.log(result[1]);

		res.json({
			success: true
		})
	})
		.catch(function(err) {
			console.log(err);
		});
});

It always ends up with "[Error: No callback function was given.]" message as bcrypt.hashAsync seems to require 4 parameters. Original, non-promisified hash method requires 3 only though. When I add empty callback to hashAsync, it works fine:

Users.prototype.setPassword = function(user) {

	return bcrypt.genSaltAsync(10).then(function(result) {
		return bcrypt.hashAsync(user.password, result,function() {});
	});

};

Is there any better way to do this, without providing empty callback as above?

EDIT:

In response to Bergi's comment.. the function will set password eventually, I just didn't get that far when posted the question. Now got this far, please let me know if something is not quite right though:

 Users.prototype.setPassword = function(user) {


        return bcrypt.genSaltAsync(10).then(function(result) {
            return bcrypt.hashAsync(user.password, result, null);
        })
        .then(function(result) {
                // store in database
                console.log("stored in database!");
                return result;
            });

    };


Answers

bcrypt.hashAsync seems to require 4 parameters. Original, non-promisified hash method requires 3 only though.

It's the other way round rather. From the docs:

hash(data, salt, progress, cb)

  • data - [REQUIRED] - the data to be encrypted.
  • salt - [REQUIRED] - the salt to be used to hash the password.
  • progress - a callback to be called during the hash calculation to signify progress
  • callback - [REQUIRED] - a callback to be fired once the data has been encrypted.

The original method took 4 arguments, hashAsync will take 3 and return a promise.

However, in your code you were only passing two. You don't need to pass an empty function though, that the parameter is not [REQUIRED] means you can pass null (or any other falsy value) for it. bcrypt will create such an empty function itself. So use

function (data) {
    return bcrypt.genSaltAsync(10).then(function(result) {
        return bcrypt.hashAsync(data.password, result, null);
    });
}
Posted on by Bergi