使用其他模块中的函数,避免异步回调地狱

Avoiding callback hell with async, using functions from other modules

本文关键字:异步 回调 地狱 函数 其他 模块      更新时间:2023-09-26

我有一个用户模块,我在其中定义要在代码中使用的函数。当我创建密码时,我想使用以下功能:

用户模块:

//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:

这就是我所做的,当然这还不算太糟,但我目前一直在努力了解如何用async解决一个简单的嵌套回调问题,我不想再使用更复杂的回调嵌套。

//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);
            });
          });
        }
      });

我正在尝试做这样的事情:

//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() {
        }
      ]);
    }
  });

我看了不少例子,但似乎找不到有人在异步中调用外部模块代码的地方。

感谢@Bergi的反馈,我将研究承诺。不管是否有人想这样做,这里是我的解决方案。我强烈建议查看异步瀑布文档——这是我发现的一些更好的材料。

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)
    }
  });
})