节点js函数需要一个返回值,但值来自callback,所以不能被返回

对于令人困惑的标题抱歉,我会试图解释

我正在使用expression式和自定义validation函数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(函数(值){..})没有完成执行,直到我收到callback,但我不知道我怎么能做到这一点,如果有的话。

编辑:纠正错误

它看起来像expression式不支持asynchronousvalidation,所以唯一的方法就是实现自定义中间件。 它可以看起来像这样:

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

它可以作为通用的解决scheme,使expression式无法进行asynchronousvalidation:我们将所需的所有数据都放在一个单独的中间件中,然后将其注入为新字段,然后通过expression式进行validation。

对于这样的情况,您需要反转呼叫的顺序。 就像是:

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

基本上,你需要在使用它们之前获取这些值(如果这样说的话,看起来很明显,但是asynchronous编程往往会使这个显然不那么明显)。

如果你需要检查多个asynchronous项目,那么你需要以某种方式链接在一起。 如果需要,asynchronous库可以提供帮助。