重复输出到控制台 – 我必须在哪里插入我的callback?

这是我的代码到目前为止:

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(); 

会发生什么事只是在第一个命令popup“input您的select”文本。 您仍然可以input数字并执行其他选项。

这是我在控制台上得到的:

 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"]()完成后),“input您的select”再次popup。 喜欢这个:

 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"]();之前popup“Enter your choice” options[data]["execute"](); 已经完成了。 如果我把它放在read结束,我得到一个无限循环/超过最大调用堆栈大小。

或者我可以添加callbackoptions[data]["execute"](); ? 就像是

 function( null, read){ options[data]["execute"](); }; 

您所遇到的基本问题是在数据库方法完成之后,您的消息显示应该发生。 你通过callback报告完成,但问题是并不是所有的方法都提供callback来确定何时完成。 现在,即使这样做了, 当您调用方法时您也没有注册callback 。 所以你应该在你所有的函数中定义一个callback参数,然后在你的阅读过程中注册一个callback函数

 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(); 

使用承诺

这种情况的另一种解决scheme是使用承诺。 这样,您对数据库的调用可以返回一个承诺,稍后您可以使用它来等待适当的响应。

我在这个答案中使用了Q Promises ,但是你可以使用任何你想要的这种types的库。 你可以看到如何在这里得到你的项目的Q.

我们可以从确保你的数据库服务返回一些东西开始,在这种情况下是一个承诺。 对于这个问题,我将使用Q.ninvoke将基于callback的函数变成一个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); }); }; 

你可以注意到我所有的服务方法现在都返回了一些东西,而在你原来的devise中它们是无效的。

最后,你可以改变你的阅读程序为:

 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。 承诺执行的成功保证您不会显示“直到完成其他任务时input您的select”。

瞧,输出是:

 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} 

正是你想要的。

 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: "); }); }; 

您可以考虑使用内置的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();