简体   繁体   中英

Avoiding callback hell with async, using functions from other modules

I have a user module where I am defining functions to be used across the code. When I am creating a password I would like to utilize these functions:

User Module:

//insert a local user into the database
User.prototype.insertLocalUser = function (email, password, cb) {

  var sql = "INSERT INTO VCUSER ( VCUSER_EMAIL, VCUSER_PASSWORD ) values ('" + email
    + "','" + password + "')";

  db.get().query(sql, function (err, rows) {
    if (err) return cb(err);

    return cb(err, rows);
  });
};

//generate hash function for password
User.prototype.generateHash = function (password, cb) {

  bcrypt.genSalt(10, function(err, salt) {
    if (err) return cb(err);

    bcrypt.hash(password, salt, null, function(err, hash) {
      return cb(err, hash);
    });
  });
};

Passport.js:

Here is where I am doing so, granted this isn't too bad but I am currently stuck on trying to understand how to fix a simple nested callback issue with async and I don't want to move forward with a much more complex callback nest.

//minor callback hell
      user.findByEmail(email, function (err, rows) {
        if (err) return done(err);

        if (rows.length) { //user must already exist prompt user
          return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
        } else {

          user.generateHash(password, function (err, hash) {
            if (err) return done(err);

            //insert a user with the newly hashed password into the database
            user.insertLocalUser(email, hash, function (err, rows) {
              if (err) return done(err);

              user.VCUSER_USERID = rows.insertId;

              //return the user we are done, they should be serialized and redirected
              return done(null, user);
            });
          });
        }
      });

I am trying to do something like this:

//first search to see if the user already exists
  user.findByEmail(email, function (err, rows) {
    if (err) return done(err);

    if (rows.length) { //user must already exist prompt user
      return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
    } else {
      async.series([
        //code avoid callback hell here
        user.generateHash... {

        }

        user.insertLocalUser() {

        }
      ]);
    }
  });

I have looked at quite a few examples but I cannot seem to find something where someone is calling an outside modules code inside async.

I will be looking into promises thanks to @Bergi's feedback. Regardless if anyone is looking to do this here was my solution. I highly recommend reviewing the async waterfall documentation it was some of the better material I have found.

async.waterfall([
    //look in database for existing users with email inputed return as results
    function findUser(cb) {
      var sql = "SELECT * FROM VCUSER WHERE VCUSER_EMAIL = '" + email + "'";

      db.get().query(sql, function (err, result) {
        if (err) { cb(err); }

        cb(null, result);
      });
    },
    //check if there were any results, if so prompt, if not continue with user creation
    function generateHash(result, cb) {
      if (result.length) { return done(null); } //TODO determine how this is handled back to UI

      bcrypt.genSalt(10, function(err, salt) {
        if (err) { cb(err); }

        bcrypt.hash(password, salt, null, function(err, hash) {
          cb(null, hash);
        });
      });
    },
    //using recently generated hash create a user
    function insertNewUser(hash, cb) {
      var sql = "INSERT INTO VCUSER ( VCUSER_FIRSTNAME, VCUSER_LASTNAME, VCUSER_EMAIL, VCUSER_PASSWORD ) " +
        "values ('" + req.body.firstName + "','" + req.body.lastName + "','" + email + "','" + hash + "')";

      db.get().query(sql, function (err, rows) {
        if (err) { cb(err); }

        cb(null, rows);
      });
    }
  ], function (err, rows) {
    if (err) { return done(err); }
    else {
      user.VCUSER_USERID = rows.insertId;
      return done(null, user)
    }
  });
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM