我的设置如下:
server.js
需要utils.js
utils.js
将数据从mongodb加载到内存中并将其导出server.js
使用utils.js
导出我担心的问题是mongodb调用是异步的。 utils.js在mongodb调用完成之前返回,这意味着server.js在require之后继续执行时将使用未定义的变量。
解决此问题的最佳方法是什么?我唯一能想到的是将我的server.js代码包装在一个巨大的回调中,并将其传递给进行mongodb调用的函数。对我来说这似乎有点乱,有没有更好的方法呢?
代码:
server.js
var utils = require("./modules/utils.js");
console.log(utils);
//Do whatever
utils.js
var mods = [];
var db = require("mongojs").connect("localhost", ["modules"]);
db.modules.find({}, function(err, modules){
mods = modules;
});
module.exports = mods;
答案 0 :(得分:5)
你所指的是“回调地狱”。最简单的方法是使用简化它的Promise库。
我使用了名为bluebird
的节点包。
var mysql = require("mysql");
var hash = require("password-hash");
var Promise = require("bluebird");
var settings = require("../settings");
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
var db_config = {
user:settings.db.user,
password:settings.db.password,
database:settings.db.database
};
var con = mysql.createPool(db_config);
function query(sql) {
return con.getConnectionAsync().then(function(connection) {
return connection.queryAsync(sql)
.spread(function(rows,fields) {
return rows;
}).finally(function() {
connection.release();
});
});
}
这是我编写的一个非常基本的数据库模块,它使用bluebird
来promisify
数据库对象。
以下是它的使用方法。它回报了一个承诺!这样做的好处是它不仅可以恢复回调地狱的混乱,它还可以确保您的代码异步运行,并且在事情停止处理之前函数不会返回,就像在这种情况下,数据库查询一样。
function login(user) {
//check for player existance
var query = 'SELECT p.name,p.password,p.id, pd.x, pd.y FROM player p INNER JOIN player_data pd ON p.id = pd.id WHERE p.name='+mysql.escape(user);
return db.select(query).then(function(rows) {
if (!rows.length) return;
return [
rows[0]
];
});
}
注意你如何返回一个promise,这样你就可以调用then
或spread
方法来获取刚查询过的那些数据库值,而不必担心rows
是否会被定义当你想要使用它时。
答案 1 :(得分:0)
正如您所说,您需要将整个服务器包装在回调中。 Node.js以这种方式工作,它本质上是异步的。服务器需要经过3个阶段:init,serve和deinit。在您的情况下,该数据库代码进入init阶段。你可以写这样的东西。
//server.js
var utils = require ("./modules/utils");
var init = function (cb){
//init the utils module, the http server and whatever you need
utils.init (function (error){
if (error) return handleError (error);
cb ();
});
};
var serve = function (){
//Start listening to the http requests
};
var deinit = function (cb){
//This is typically executed when a SIGINT is received, see link1
};
init (serve);
//utils.js
//You could write a wrapper for the db instance, see link2
var mongodb = require ("mongojs");
var db;
module.exports.init = function (cb){
db = mongodb.connect ("localhost", ["modules"]);
db.modules.find ({}, function (err, modules){
if (err) return cb (err);
cb (null, modules);
});
};
我不建议使用promises,它们比原始回调慢。你根本不需要它们。