Javascript 无法从函数调用mongodb方法
所以我做了一个用户登录,数据库是mongodb,它工作得非常完美。但是,我想在用户登录后再次调用mongodb,因此我决定将其拆分为单独的函数。但是,当我尝试使用登录脚本并将其转换为函数时,数据库无法打开。这是没有意义的,因为我使用的代码与路线内部的代码完全相同。这可以在函数中完成吗?有人知道发生了什么事吗 下面是证明dB无法打开的调试程序的代码和图像 路线Javascript 无法从函数调用mongodb方法,javascript,angularjs,mongodb,function,database,Javascript,Angularjs,Mongodb,Function,Database,所以我做了一个用户登录,数据库是mongodb,它工作得非常完美。但是,我想在用户登录后再次调用mongodb,因此我决定将其拆分为单独的函数。但是,当我尝试使用登录脚本并将其转换为函数时,数据库无法打开。这是没有意义的,因为我使用的代码与路线内部的代码完全相同。这可以在函数中完成吗?有人知道发生了什么事吗 下面是证明dB无法打开的调试程序的代码和图像 路线 // Listen for Upload file router.post('/uploadFile', function
// Listen for Upload file
router.post('/uploadFile', function (req, res) {
upload(req, res, function (err) {
if (err) {
console.log("Error uploading file");
} else {
//var databaseName = "E-learn", collection = "Accounts";
var username = req.body.username ;
var fileName = req.file.filename ;
var filePath = req.file.path ;
console.log(username);
console.log("GET " + req.file.fieldname);
console.log("GET " + req.file.filename);
console.log("GET " + req.file.orignalName);
console.log("GET " + req.file.path);
var result = findOne(username);
res.json(result);
}
});
});
函数调用
function findOne(username){
var databaseName = "E-learn", collection = "Accounts";
var db = new Db(databaseName, new Server('localhost', 27017));
db.open(function (err, db) {
console.log(databaseName + ": opened");
console.log(db);
db.collection(collection).findOne({username:username}, function (err, doc) {
assert.equal(null, err);
if (doc != null) {
console.log("Found");
// db.close();
return "Found" ;
} else {
console.log("Not Found");
// db.close();
return "Not found";
}
db.close();
});
});
console.log("Did not open")
db.close();
return 0 ; // Should not be called
}
正如第一次查看时所观察到的,您的代码中有几个问题
不确定运行的是哪个ES版本,但如果您想采用同步方法,请尝试此版本的findOne。Async/Await使异步代码同步
async function findOne(username){
var databaseName = "E-learn", collection = "Accounts";
var db = new Db(databaseName, new Server('localhost', 27017));
let db = await db.open();
// try above line first
//let {err, db} = await db.open();
let doc = await db.collection(collection).findOne({username:username});
// try above line first
//let {err, doc} = await db.collection(collection).findOne({username:username});
//assert.equal(null, err);
if (doc != null) {
console.log("Found");
// db.close();
return "Found" ;
} else {
console.log("Not Found");
// db.close();
return "Not found";
}
db.close();
//console.log("Did not open")
//db.close();
//return 0 ; // Should not be called
}
如果Async/Await出现错误,请尝试安装此软件包 大多数新引入的JavaScript开发人员都会遇到典型的异步回调问题 首先,(必须为您阅读)。这意味着,当您将函数作为某个对象的参数传递时,您不能期望函数中的代码将内联到代码中运行。可能您传递的函数将作为事件的结果被调用(连接到某物,用户单击按钮,数据库打开…),因此将来某个时候会发生。即使是1纳秒之后,也将是未来 因此,您希望它以这种方式运行:
function findOne(username){
// Start with this (step 1)
var databaseName = "E-learn", collection = "Accounts";
// Then continue with this (step 2)
var db = new Db(databaseName, new Server('localhost', 27017));
// Open the database (step 3) and the code will wait for the database to open
db.open(function (err, db) {
// Run this inline, just after db.open (step 4)
console.log("OPEN");
[...]
});
// Continue with this after the database was open (step 5)
console.log("Did not open")
db.close();
return 0 ; // Should not be called
}
但实际上发生的是:
function findOne(username){
// Start with this (step 1)
var databaseName = "E-learn", collection = "Accounts";
// Then continue with this (step 2)
var db = new Db(databaseName, new Server('localhost', 27017));
// Open the database (step 3), pass a function that will be called by the database when is open AND continue with the next step
db.open(function (err, db) {
// This function will be called when the database is open, so right now is not called.
console.log("OPEN");
[...]
});
// This is the next step after step 3 (step 4).
console.log("Did not open")
db.close();
return 0 ; // Should not be called
}
// And sometime in the future you suddenly get in console OPEN, when the database decides to run the callback you passed to it.
另一种方法是返回总是从函数返回,因此使用此嵌套函数:
function findOne(username) { // function keyword, so this is a function (number 1)
[...]
db.open(function (err, db) { // Note the function keyword here, so this is a function too (number 2)
[...]
return 1; // This return actually works, BUT affects the function where it belongs, which is function number 2 in this case.
});
[...]
return 0; // And this one is the return of the function number 1.
}
因此,假设在运行下一行代码之前,db.open
立即运行回调。尽管它不是以异步方式运行的,但回调中的返回
仍然无法返回findOne
函数
异步问题需要异步解决方案。(或者使用ES6生成器(async、await等),但目前会使您更加复杂,因为您仍然不了解代码发生了什么,更糟糕的是,何时使用生成器(因为它们与异步回调相关联),所以最好先了解JS中的异步回调)。当你理解它的时候,其实很简单。只是一些变化:
// Listen for Upload file
router.post('/uploadFile', function (req, res) {
upload(req, res, function (err) {
if (err) {
console.log("Error uploading file");
} else {
//var databaseName = "E-learn", collection = "Accounts";
var username = req.body.username ;
var fileName = req.file.filename ;
var filePath = req.file.path ;
console.log(username);
console.log("GET " + req.file.fieldname);
console.log("GET " + req.file.filename);
console.log("GET " + req.file.orignalName);
console.log("GET " + req.file.path);
// Converted the sync function to an async one, by passing a
// callback function as a parameter with 2 arguments, being
// the first the possible error and the second the data
findOne(username, function(err, result) {
if (err) {
console.log("Error uploading file");
} else {
res.json(result);
}
});
}
});
});
// Here you can see now that we have the callback parameter,
// that references the callback function we passed before and
// we can call it whenever we want
function findOne(username, callback) {
var databaseName = "E-learn", collection = "Accounts";
var db = new Db(databaseName, new Server('localhost', 27017));
db.open(function (err, db) {
if (err) {
callback(err); // If error, pass the error as first argument of the callback
} else {
console.log(databaseName + ": opened");
console.log(db);
db.collection(collection).findOne({username:username}, function (err, doc) {
if (err) {
callback(err); // As findOne is another async callback too, the same as above. Check for err
} else {
// And if everything is fine, then pass the result as the second parameter of the callback
if (doc != null) {
callback(null, "Found");
} else {
callback(null, "Not found");
}
}
db.close();
});
}
});
}
正如您可能已经注意到的,在数据库方法和路由器方法中,您将大量的函数作为回调传递
以及一些开发人员ProTip:
- 现在,只需逐行阅读代码,并尝试理解每一行上发生的事情。这样,您可能会想,“为什么我没有编写的代码是由回调生成的,而我的代码不是?”。这个问题和一些研究会对你有很大帮助
- 总是有干净的压痕。你的代码有一些问题。缩进在JavaScript中是必须的,因为它的异步特性,在JavaScript中可以有一个回调地狱,缩进在这方面帮助很大
你能修改你的代码并只发布相关的代码片段吗?我感觉到一个竞争条件问题。当findOne被调用时,打开数据库、查找记录并响应需要时间。可能会在完成之前触发res.json()。您是否注释掉了res.json(),只是为了查看在调用DB时是否写入日志?