我正在尝试编写一个简单的验证函数,它接受一个mongo_id并检查它是否存在。我能够走到这一步,但我无法将该结果传递回调用该函数的路径。
这个函数基于一个浮动的例子......它确实有效。
validateUserId = function(userId) {
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var options = {
mongos: {
ssl: false,
sslValidate: false,
}
}
isValid = false;
MongoClient.connect(vars["MONGO_URL"], options, function(err, db) {
assert.equal(null, err);
var q = db.collection("users").find({
_id: userId
}, {
_id: 1
}).toArray(function(err, record) {
assert.equal(null, err);
record.forEach(function(r) {
console.log(r);
if (r._id == userId) {
isValid = true;
}
});
db.close();
return isValid;
})
});
return isValid;
};
此功能不会返回任何内容。
如何根据查询结果正确修改此代码以返回true / false值?
我们的想法是不必将此代码放入需要进行验证的每个路径中,只需在执行其他任务(不需要访问或连接到mongodb)之前调用validateUserId()。
例如:
app.get("/performVerifiedAction",function(req,res){
if(validateUserId(req.query['userId'])){
res.send("You may pass");
}else{
res.send("Can't figure out who you are");
}
return true;
});
答案 0 :(得分:0)
validUserId
实际上是一个异步函数。
按照Node.js中的惯例,异步函数在其最后一个参数中收到回调,请参阅How to write asynchronous functions for Node.js
在Node.js style callbacks之后,callback
参数是一个在第二个参数中接收异步操作结果的函数。
// callback is a function that gets isValid as its second arguments
// by convention the first argument of these callback function is any error
// that may occur in this async operation.
validateUserId = function(userId, callback) {
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var options = {
mongos: {
ssl: false,
sslValidate: false,
}
}
isValid = false;
MongoClient.connect(vars["MONGO_URL"], options, function(err, db) {
assert.equal(null, err);
var q = db.collection("users").find({
_id: userId
}, {
_id: 1
}).toArray(function(err, record) {
assert.equal(null, err);
record.forEach(function(r) {
console.log(r);
if (r._id == userId) {
isValid = true;
}
});
db.close();
return callback(null, isValid); // instead of return isValid;
})
});
return callback(null, isValid); // instead of return isValid;
};
这是您使用validUserId
异步功能的方法:
app.get("/performVerifiedAction",function(req,res){
validateUserId(req.query['userId'], function(error, isValid) {
if(isValid) {
res.send("You may pass");
} else {
res.send("Can't figure out who you are");
}
});
});
请注意,您可以通过处理错误(将err
传递给callback
并从函数返回)来大量改进上述代码。例如:
MongoClient.connect(vars["MONGO_URL"], options, function(err, db) {
assert.equal(null, err);
// ...
可以改进为:
MongoClient.connect(vars["MONGO_URL"], options, function(err, db) {
if(!!err) {
return callback(err);
}
//...
答案 1 :(得分:0)
Node.js调用外部服务的方法是异步的。这意味着调用MongoDb函数不会阻止程序执行,因此您的validateUserId函数将始终返回false,因为稍后将调用MongoDb查找回调并且不会修改已返回的值。
要在许多路由上使用此验证,您可以将此方法修改为Express中间件,如下所示:
//Avoid connecting to MongoDb on every request, make the connection persistant
var MongoClient = require('mongodb').MongoClient;
var options = {
mongos: {
ssl: false,
sslValidate: false,
}
};
var mongo = {
db: null
};
MongoClient.connect(vars["MONGO_URL"], options, function(err, db) {
if (err) {
console.error("Error connecting to MongoDB:", err);
process.exit(1);
}
mongo.db = db;
});
// Create a middleware method that will be called in request processing chain before your handler
var validateUserId = function(req, res, next) {
var userId = req.query['userId'];
// Use findOne to validate user id. It is faster and simplier
mongo.db.collection("users").findOne({_id: userId}, {_id: 1}, function(err, record) {
if (err) {
return res.status(500).send("Error getting user");
}
if (!record) {
return res.status(403).send("Can't figure out who you are");
}
next();
});
};
然后您可以通过以下方式使用此中间件:
app.get("/performVerifiedAction", validateUserId, function(req,res){
res.send("You may pass");
});