到目前为止,这是我的代码:
var databaseUrl = "mydb";
var collections = ["users", "reports"];
var db = require("mongojs").connect(databaseUrl, collections);
newuser = {
email: "john@example.com",
password: "iLoveMongo",
sex: "male"
};
saveuser = function(user, callback) {
db.users.save(
user,
function( error, saved) {
if( error || !saved )
console.log( "User not saved");
else
console.log( "User saved" );
callback();
}
);
};
removeuser = function() {
db.users.remove(
{
sex: "male"
},
function( error, removed) {
if( error || !removed )
console.log( "User not deleted");
else
console.log( "User deleted" );
}
);
};
finduser = function() {
db.users.find(
{
sex: "male"
},
function(error, users) {
if( error || !users.length )
console.log( "No male Users found");
else
{
console.log( "male Users found" );
users.forEach(
function(maleUser) {
console.log(maleUser);
}
);
}
}
)
};
updateuser = function() {
db.users.update(
{
email: "john@example.com"
},
{
$set: { password: "iReallyLoveMongo" }
},
function(err, updated) {
if( err || !updated )
console.log("User not updated");
else
console.log("User updated");
}
);
}
var options = {
1: {
option: "Save a User",
execute: saveuser.bind(null, newuser, finduser)
},
2: {
option: "Remove a User",
execute: removeuser
},
3: {
option: "Find a User",
execute: finduser
},
4: {
option: "Update a User",
execute: updateuser
}
}
function read() {
console.log("");
console.log(" Enter your choice: ");
stdin = process.stdin;
stdin.setEncoding('utf8');
stdin.on('data', choice);
};
function choice (data) {
data = parseInt(data);
console.log("You entered: " + data);
console.log("You choose to do: " + options[data]["option"]);
options[data]["execute"]();
};
read();
只有在第一个命令弹出“输入您的选择”文本时才会发生什么。您仍然可以输入数字并执行其他选项。
这是我在控制台上得到的:
PS C:\Users\Benni\Documents\nodejs> node .\mongotest\app.js
Enter your choice:
1
You entered: 1
You choose to do: Save a User
User saved
male Users found
{ _id: 5386ba18463a008011fe6213,
email: 'john@example.com',
password: 'iLoveMongo',
sex: 'male' }
3
You entered: 3
You choose to do: Find a User
male Users found
{ _id: 5386ba18463a008011fe6213,
email: 'john@example.com',
password: 'iLoveMongo',
sex: 'male' }
我想要的是,在每次成功命令后(options[data]["execute"]()
完成后),再次弹出“输入您的选择”。像这样:
PS C:\Users\Benni\Documents\nodejs> node .\mongotest\app.js
Enter your choice:
1
You entered: 1
You choose to do: Save a User
User saved
male Users found
{ _id: 5386ba18463a008011fe6213,
email: 'john@example.com',
password: 'iLoveMongo',
sex: 'male' }
Enter your choice:
3
You entered: 3
You choose to do: Find a User
male Users found
{ _id: 5386ba18463a008011fe6213,
email: 'john@example.com',
password: 'iLoveMongo',
sex: 'male' }
我必须再次调用read()?如果我将其放在choice
的末尾,则会在options[data]["execute"]();
完成之前弹出“输入您的选择”。如果我把它放在read
的末尾,我将得到一个无限循环/超出最大调用堆栈大小。
或者我可以向options[data]["execute"]();
添加回调吗?像
function( null, read){
options[data]["execute"]();
};
答案 0 :(得分:1)
您遇到的基本问题是,在数据库方法完成后,您的消息显示应该会发生。您通过回调报告完成,但问题是并非所有方法都提供回调以确定何时完成。现在即使你没有,你在调用方法时没有注册回调。所以你应该在你的所有函数中定义一个回调参数,然后在你的阅读中注册一个回调:
newuser = {
email: "john@example.com",
password: "iLoveMongo",
sex: "male"
};
saveuser = function(user, callback) {
db.users.save(
user,
function( error, saved) {
if( error || !saved )
callback( "User not saved");
else
callback(saved);
}
);
};
removeuser = function(callback) {
db.users.remove(
{
sex: "male"
},
function( error, removed) {
if( error || !removed )
callback( "User not deleted");
else
console.log( "User deleted" );
callback();
}
);
};
finduser = function(callback) {
db.users.find(
{
sex: "male"
},
function(error, users) {
if( error || !users.length )
callback( "No male Users found");
else
{
console.log( "male Users found" );
callback(null, users);
}
}
)
};
updateuser = function(callback) {
db.users.update(
{
email: "john@example.com"
},
{
$set: { password: "iReallyLoveMongo" }
},
function(err, updated) {
if( err || !updated )
callback("User not updated");
else
console.log("User updated");
callback(null, updated);
}
);
}
var options = {
1: {
option: "Save a User",
execute: saveuser.bind(null, newuser)
},
2: {
option: "Remove a User",
execute: removeuser
},
3: {
option: "Find a User",
execute: finduser
},
4: {
option: "Update a User",
execute: updateuser
}
}
function read() {
console.log("");
console.log(" Enter your choice: ");
stdin = process.stdin;
stdin.setEncoding('utf8');
stdin.on('data', choice);
};
function choice (data) {
data = parseInt(data);
console.log("You entered: " + data);
console.log("You choose to do: " + options[data]["option"]);
options[data]["execute"](function(err, res){
if(err){
console.log(err);
}
if(res){
if(Array.isArray(res)){
res.forEach(function(item){
console.log(item);
})
} else {
console.log(res);
}
}
console.log(" Enter your choice: ");
});
};
read();
使用承诺
此案例的另一种解决方案是使用promises。这样,您对数据库的调用可以返回一个承诺,您可以稍后使用该承诺等待适当的响应。
我在这个答案中使用了Q Promises,但你可以使用你想要的任何其他库。您可以查看如何为项目获取Q here。
我们可以从确保您的数据库服务返回一些内容开始,在这种情况下是一个承诺。对于这个问题,我将使用Q.ninvoke
将基于回调的函数转换为promise。
var Q = require('q');
saveUser = function(user) {
return Q.ninvoke(db.users,"save", user)
.then(function(user){
console.log("User saved: %j", user);
})
.catch(function(error){
console.log("Error while saving: %s", error);
});
};
removeUser = function() {
return Q.ninvoke(db.users,"remove", {sex: "male"})
.then(function(result){
console.log("User removed: %j", result);
})
.catch(function(error){
console.log("Error while removing: %s", error);
});
};
findUser = function() {
return Q.ninvoke(db.users,"find", {sex: "male"})
.then(function(user){
console.log("User found: %j", user);
})
.catch(function(error){
console.log("Error while finding: %s", error);
});
};
updateUser = function() {
return Q.ninvoke(db.users,"update",
{
email: "john@example.com"
},
{
$set: { password: "iReallyLoveMongo" }
})
.then(function(user){
console.log("User updated: %j", user);
})
.catch(function(error){
console.log("Error while updating: %s", error);
});
};
您可以注意到我的所有服务方法现在都返回了一些东西,而在原始设计中它们是无效的。
最后,您可以将阅读程序更改为:
function read() {
console.log("");
console.log(" Enter your choice: ");
stdin = process.stdin;
stdin.setEncoding('utf8');
stdin.on('data', choice);
};
function choice (data) {
data = parseInt(data);
console.log("You entered: " + data);
console.log("You choose to do: " + options[data]["option"]);
options[data]["execute"]().then(function(){
console.log("Enter your choice: ")
});
};
read();
请注意,在这种情况下,options [data] [“execute”]的执行如何使用promise。承诺执行的成功保证您不会显示“在完成其他任务之前输入您的选择”。
瞧,输出是:
Enter your choice:
1
You entered: 1
You choose to do: Save a User
User saved: [{"email":"john@example.com","password":"iLoveMongo","sex":"male","_id":"5388f57035a2eda13b7e4ea7"},{"n":0}]
Enter your choice:
2
You entered: 2
You choose to do: Remove a User
User removed: {"n":2}
正是你想要的。
答案 1 :(得分:0)
function choice (data) {
data = parseInt(data);
console.log("You entered: " + data);
console.log("You choose to do: " + options[data]["option"]);
options[data]["execute"]();
process.nextTick(function(){
console.log("");
console.log(" Enter your choice: ");
});
};
答案 2 :(得分:0)
您可以考虑使用内置的readline模块来帮助您完成以下任务:
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function choiceHandler(choice) {
choice = parseInt(choice, 10);
if (isNaN(choice))
console.log('Bad choice, try again');
else {
console.log('You entered: ' + choice);
console.log('You chose to do: ' + options[choice]['option']);
}
rl.prompt();
}
console.log('');
rl.setPrompt(' Enter your choice: ');
rl.on('line', choiceHandler);
rl.prompt();