未达到的功能

functions not being reached

本文关键字:功能 未达到      更新时间:2023-09-26

我正在尝试建立登录服务原型,这是我正在进行的这个个人项目的服务器端部分的第一步。我试图在这里和这里引用代码,因为它来自Learning Node.js(Marc Wandschneider)的书,该书已经出版了三年,因此已经被证明是有效的。

我的实际服务器代码可以在这个StackOverflow链接中找到。我跳过了数据库部分,因为我在启动它时遇到了问题,相反,我将./helpers/users.js设置为:

exports.version = "0.0.1";
var async = require('async'),
    bcrypt = require('bcrypt');
var helpers = require('./helpers.js');
function User(id, email, displayName, password, deleted)
{
    this.userID = id;
    this.email = email;
    this.displayName = displayName;
    if (User.connectedToDatabase) this._password = password;
    else
    {
        bcrypt.genSalt(10, function (err, salt) {
            // this, for some reason, isn't getting called. Literally, I never see "I'm here"
            console.log("I'm here...");
            bcrypt.hash(password, salt, function (err, hash) { 
                if (!err)
                {
                    this._password = hash;
                    console.log("this._password == " + this._password);
                }
                else
                {
                    console.log("Error occurred: ");
                    console.log(err);
                }
            })
        });
    }
    //this._password = password;
    this.deleted = deleted;
}
User.connectedToDatabase = false;
User.prototype.userID = 0;
User.prototype.email = null;
User.prototype.displayName = null;
User.prototype._password = null;
User.prototype.deleted = false;
User.prototype.checkPassword = function (password, callback)
{
    bcrypt.compare(password, this._password, callback); // returns false
}
User.prototype.responseObject = function() {
    return {
        id: this.userID,
        email: this.email,
        displayName: this.displayName
    };
}
exports.login = function (req, res) {
    var dblessPrototype = true;
    // get email address from req.body, trim it and lowercase it
    var email = req.body.emailAddress ? 
        req.body.emailAddress.trim().toLowerCase() :
        "";
    // begin the login process
    async.waterfall([
        // prelimninary verification: make sure email,password are not empty, and that email is of valid format
        function(cb) 
        {
            // if no email address
            if (!email)
            {
                // send error via cb
                cb(helpers.missingData("email_address"));
            }
            // if '@' not found in email address
            else if (email.indexOf('@') == -1)
            {
                // then email address is invalid
                cb(helpers.invalidData("email_address"));
            }
            // if password is missing from req.body
            else if (!req.body.password)
            {
                // tell next function about that
                cb(helpers.missingData("password"));
            }
            // we are ready to move on otherwise
            else cb(null);
        },
        // TODO: lookup by email address
        // check the password
        function (userData, cb)
        {
            var u;
            if (dblessPrototype)
            {
                u = new User(0, 
                    "admin@mikewarren.me",
                    "SampleAdmin",
                    "Sample0x50617373");
            }
            else 
            {
                u = new User(userData);
            }
            console.log("u._password == " + u._password);
            console.log("req.body.password == " + req.body.password);
            u.checkPassword(req.body.password, cb);
        },
        // time to set status of authenticiation
        function (authOK, cb)
        {
            console.log("authOK == " + authOK);
            if (!authOK)
            {
                cb(helpers.authFailed());
                return;
            }
            // set status of authenticiation in req.session
            req.session.loggedIn = true;
            req.session.emailAddress = req.body.emailAddress;
            req.session.loggedInTime = new Date();
        }
    ],
    function (err, results)
    {
        if (err)
        {
            console.log(JSON.stringify(err, null, ''t'));
            if (err.code != "already_logged_in")
            {
                helpers.sendFailure(res, err);
                console.log("Already logged in...");
            }
        }
        else
        {
            helpers.sendSuccess(res, { loggedIn: true });
            console.log("Log in successful...");
        }
    });
}

在密码检查中,u._password为空(它从未被设置,这意味着异步bcrypt.genSalt()代码没有被调用。此外,数组中的最后一个函数,即async.waterfall()的第一个参数,也没有调用async.waterfall()的最后一个子参数。

为什么不调用这些函数,我该怎么办?

编辑:我通过替换使异步密码加密同步

bcrypt.genSalt(10, function (err, salt) {
        // this, for some reason, isn't getting called. Literally, I never see "I'm here"
        console.log("I'm here...");
        bcrypt.hash(password, salt, function (err, hash) { 
            if (!err)
            {
                this._password = hash;
                console.log("this._password == " + this._password);
            }
            else
            {
                console.log("Error occurred: ");
                console.log(err);
            }
        })
    });

this._password = bcrypt.hashSync(password, bcrypt.genSaltSync(10));

它进入密码比较部分,挂起一段时间,然后进入数组的下一个(最后一个)元素,而不向控制台打印任何内容。就好像那个元素被跳过了。

EDIT下载完整的应用程序并在家里摆弄它之后。

我更改了您的代码以包含setTimeout方法,并在User函数中强制执行了this上下文。在我自己的机器上运行所有的代码,我从你的git repo下载了这些代码,我得到了用户身份验证,应用程序查找不存在的index.html。所以身份验证正在工作!

代码没有等待salt和hash完成后再继续。如果你正在向数据库写入,你可以进行"预"保存并使用promise。但这会给你一个暂时的解决办法。

function (cb, userData)
    {
        var u;
        if (dblessPrototype)
        {
          var authOK;
            u = new User(0,
                "admin@mikewarren.me",
                "SampleAdmin",
                "Sample0x50617373");
                setTimeout(function () {
                  console.log("u._password == " + u._password);
                  console.log("req.body.password == " + req.body.password);
                  console.log(u)
                  u.checkPassword(req.body.password, function(err, res) {
                    if (err) {
                      console.log(err)
                    } else {
                      console.log(res)
                      // USER AUTHENTICATED
                      cb(null, true)
                    }
                    return res;
                  });
                }, 1000)
        }
        else
        {
            u = new User(userData);
    }
}

在用户对象生成器中将this分配给self

function User(id, email, displayName, password, deleted)
{
    this.userID = id;
    this.email = email;
    this.displayName = displayName;
    var self = this
    if (User.connectedToDatabase) this._password = password;
    else
    {
        bcrypt.genSalt(10, function (err, salt) {
            // this, for some reason, isn't getting called. Literally, I never see "I'm here"
            console.log("I'm here...");
            bcrypt.hash(password, salt, function (err, hash) {
                if (!err)
                {
                    self._password = hash;
                    console.log("this._password == " + self._password);
                }
                else
                {
                    console.log("Error occurred: ");
                    console.log(err);
                }
            })
        });
    }
    // this._password = password;
    this.deleted = deleted;
}

我应该补充一点,使用setTimeout不是一种推荐的方法,而是一种展示问题所在的方法。理想情况下,这应该使用回调、promise或生成器来完成。