我有一个处理mongodb数据库的开源项目。我正在尝试创建一个查询数据库以检查条目是否存在的函数。
问题是当if_exists()
返回true或false时它会返回undefined,因为mongodb驱动程序函数是异步的。该文件为Query.js,我在此处尝试了解决问题What is the right way to make a synchronous MongoDB query in Node.js?的解决方案,但仍然使用get方法获得了未定义的结果。
使这项工作的最佳方法是什么?
单元测试的输出如下:
running unit tests...
add query test
exists tests:
get: undefined
{}
should be true: undefined
get: undefined
{}
should be false:undefined
Captains Logs listening on port 3000
Captains_Logs v0.5.0-21
[ { name: 'rhcp', _id: 50cbdcbe9c3cf97203000002 } ]
[ { name: 'os', _id: 50cbdcbe9c3cf97203000001 } ]
您可以在WeaponXI/cplog
浏览整个代码或者快速查看query.js代码:
var DB = require('../../lib/db.js').DB;
function methods() {
//query object
var Q = {};
//will act as our private variables to workaround asynchronous functions.
//will delete non-required ones when done -- we don't have to, but just for continuity.
exports.privates = {};
//add tag to collection
Q.add = function(tag) {
if (typeof tag === "string") {
//maybe we are adding a tag by name
var obj = {
name: tag
};
} else if (typeof tag === "object" && tag.name) {
//maybe the tag object was specified, and tag's name was provided
var obj = tag;
}
require('mongodb').connect(DB.mongo_url, function(err, db) {
db.collection('tags', function(err, coll) {
coll.insert(obj, {
safe: true
}, function(err, result) {
console.log(result);
});
});
});
}
var callback = {
_set: function(key, val) {
exports.privates[key] = val;
//console.log(JSON.stringify(privates));
},
_get: function(key) {
console.log("get: "+exports.privates.key);
console.log(JSON.stringify(exports.privates));
return exports.privates[key];
},
_unset: function(key) {
delete privates[key];
}
}
var if_exists = function(query, where, callback) {
require('mongodb').connect(DB.mongo_url, function(err, db) {
db.collection(where, function(err, coll) {
coll.findOne(query, function(e, r) {
//console.log(r);
if (r === null) {
callback._set("does_exist", false);
} else {
callback._set("does_exist", true);
}
});
});
});
var result = callback._get("does_exist");
// delete privates.does_exist;
return result;
}
Q.if_exists = function(query, where) {
if_exists(query, where, callback);
}
return Q;
}
var query = exports.query = methods();
function unit_test_add() {
console.log("add query test");
query.add("os");
query.add({
name: "rhcp"
});
}
function unit_test_if_exists() {
console.log("exists tests:");
console.log("should be true: " + query.if_exists({
name: "os"
}, "tags"));
console.log("should be false:" + query.if_exists({
name: "ossuruk"
}, "tags"));
}
function unit_tests() {
console.log("running unit tests...");
unit_test_add();
unit_test_if_exists();
}
unit_tests();
感谢JohnnyHK!
答案 0 :(得分:6)
你不能使用异步结果作为函数的返回值。就这么简单。您必须通过作为函数参数提供的回调将异步结果传递给调用者(或使用期货/承诺并有效推迟该步骤,但这更复杂)。
if_exists
应该是这样的:
var if_exists = function(query, where, callback) {
require('mongodb').connect(DB.mongo_url, function(err, db) {
db.collection(where, function(err, coll) {
coll.findOne(query, function(e, r) {
//console.log(r);
if (r === null) {
callback(e, false);
} else {
callback(e, true);
}
// You should either close db here or connect during start up
// and leave it open.
db.close();
});
});
});
}