猫鼬验证竞赛条件?

时间:2012-06-05 15:01:45

标签: validation node.js mongoose race-condition

我有一个名为Application的模型:

var ApplicationSchema = new mongoose.Schema({
name       : {type: String, validate: [uniqueName, 'Unique Name']},
dateCreated: Date,
containers : [ContainerSchema]
});
mongoose.model('Application', ApplicationSchema);
var Application = database.model('Application');

在保存时调用名为uniqueName的验证函数:

function uniqueName(name)
{
console.log('In Unique Name function');
Application.find({}, function(error, documents) {
    for(var i = 0; i < documents.length; i++) {
        if(documents[i].name == name) {
            console.log('About to return false');
            return false;
        }
    }
});
return true;
}

稍后在代码中我将一些数据放入模型并保存:

newApplication.name = request.body.name;
newApplication.save(function(error) {
    console.log('Callback for save');
    if(error) {
        console.log('error if statement');
        response.statusCode = 409;
        response.end();
    }
    console.log('Done with callback');
});
response.statusCode = 201;
response.end();

当我使用一个非唯一的名称测试时,我得到了201响应以及来自终端的以下输出:

In Unique Name function
Callback for save
Done with callback
About to return false

我做错了什么,或者这真的是Mongoose的竞争条件?

1 个答案:

答案 0 :(得分:0)

当您的验证器是异步的(就像在这里一样)时,它需要接受第二个参数,该参数是必须使用true或false调用的回调,具体取决于验证是否通过。所以:

function uniqueName(name, callback)
{
    Application.find({}, function(error, documents) {
        for(var i = 0; i < documents.length; i++) {
            if(documents[i].name == name) {
                return callback(false);
            }
        }
        return callback(true);
    }
}

然而,这不是很有效;你应该:

过滤您的find,而不是获取所有文档并手动搜索它们。 e.g。

Application.find({name: name} ...

或更好:

name上创建一个唯一索引,让mongo确保您的唯一性。 e.g。

var ApplicationSchema = new mongoose.Schema({
    name: {type: String, unique: true}, 
    ...