1

为令人困惑的标题道歉,我将尝试解释

我正在使用带有express-form的 node.js和自定义验证功能,如下所示:

app.post('/register', form(
    field("username").trim().required().custom(function(value) {
       //Works correctly
       if (!user.validUsername(value)) {
           throw new error("Invalid username");
       }

       //Does not work due to callback
       user.uniqueUsername(value, function(uniqueUsername) {
            if (!uniqueUsername) {
                //Not unique, throw error
                throw new Error("username is already taken");
                //Could be subsituted for return "whatever"; and it would still be the same problem
            }
        });
    }),
    registerAttempt);
};

// ...
//Example function for brevity  
user.uniqueUsername = function(username, callback) {
    User.findOne({username: username}, function(err, user) {
        if (err) { throw err; }
        callback(user === null);
    });
}

我需要一种方法来重组它,以便 .custom(function(value) { .. }) 在收到回调之前不会完成执行,但我不知道该怎么做,如果有的话。

编辑:更正错误

4

2 回答 2

2

看起来 express-form 不支持异步验证,所以唯一的方法是实现自定义中间件。它看起来像这样:

app.post('/register',
    function (req, res, next) { //here it goes
        user.uniqueUsername(req.body.username, function(uniqueUsername) {
            req.body.uniqueUsername = uniqueUsername; //we can't do anything about it yet
            next();
        });    
    },

   form(field('username').trim().required().custom(function(value) {
        if (!user.validUsername(value)) {
             throw new error("Invalid username");
        }   
   }),
   field('uniqueUsername').custom(function(value) {
        if (!value) {
             throw new Error("username is already taken");
        }   
   }),

   registerAttempt);

它可以用作 express-form 无法进行异步验证的通用解决方法:我们将所需的所有数据提取到单独的中间件中,并将其作为新字段注入,然后由 express-form 验证。

于 2013-10-12T22:54:54.137 回答
-1

对于这种情况,您需要颠倒调用顺序。就像是:

User.findOne({username: username}, function(err, uniqueUsername) {
    if (err) { throw err; }

    app.post('/register', form(
        field("username").trim().required().custom(function(value) {
            if (!user.validUsername(value)) {
                throw new error("Invalid username");
            }
            if (!(uniqueUsername === null)) {
                //Not unique, throw error
                throw new Error("username is already taken");
            }
        }),
        registerAttempt
    );
};

基本上,您需要在使用它们之前获取值(当这样说时,这似乎很明显,但异步编程往往会使明显的不那么明显)。

如果您需要检查多个异步项目,那么您需要以某种方式将它们链接在一起。如有必要,异步库可以提供帮助。

于 2013-10-12T23:55:36.627 回答