Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 向控制台重复输出-我必须在哪里插入回调?_Javascript_Node.js_Powershell_Command Line - Fatal编程技术网

Javascript 向控制台重复输出-我必须在哪里插入回调?

Javascript 向控制台重复输出-我必须在哪里插入回调?,javascript,node.js,powershell,command-line,Javascript,Node.js,Powershell,Command Line,这是我目前的代码: var databaseUrl = "mydb"; var collections = ["users", "reports"]; var db = require("mongojs").connect(databaseUrl, collections); newuser = { email: "john@example.com", password: "iLoveMongo", sex:

这是我目前的代码:

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

您可以考虑使用内置模块来帮助您完成以下部分:

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

您面临的基本问题是,消息的显示应该在数据库方法完成后进行。您通过回调报告完成情况,但问题是并非所有方法都提供回调来确定何时完成。现在,即使调用了该方法,您也没有在调用该方法时注册回调。因此,您应该在所有函数中定义回调参数,然后在读取期间注册回调:

使用承诺

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

我已经在这个答案中使用了,但是你可以使用任何其他你想要的这类库。您可以看到如何为您的项目获得Q

我们可以首先确保您的数据库服务返回一些东西,在这种情况下这是一个承诺。对于这个问题,我将使用
Q.ninvoke
,它将基于回调的函数转换为承诺

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();
请注意,在这种情况下,选项[data][“execute”]的执行是如何使用承诺的。承诺执行的成功保证您不会显示“在其他任务完成之前输入您的选择”

瞧,输出是:

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}

这正是您想要的。

我在nodejs中异步执行此操作,因此在完成
选项[data][“execute”]()
之前会弹出“输入您的选择”。我正在寻找在
options[data][“execute”]()之后再次显示“输入您的选择”的东西是done@mles然后,您需要向函数中添加回调/承诺/事件,以便知道它们何时完成。使用process.nexttick的最简单方法也尝试过,添加了一个回调到
read()
choice()
,但没有得到我想要的结果。我要么没有得到输出,要么它崩溃了,超出了无限循环/最大调用堆栈。@NikolayLukyanchuk得到了与下一个时钟相同的输出。我应该在哪里调用
选项[data][“execute”]()
?如果我在else分支中添加它,`Enter your chouice`仍然会在执行
options[data][“execute”]()
之前出现如果
options[data][“execute”()
不能保证同步,那么就执行类似于
返回options[data][“execute”]()并调用
rl.prompt()当你想显示提示时手动。Hei Edwin,谢谢你!没有承诺的正确解决方案会是什么样子?@mles就像我在前两段中解释的那样。好的,我用回调修改了4个函数中的3个。怎么样
saveuser()
?我如何修改它,使其具有2个回调?我想执行的是
saveuser()
,然后执行
finduser()
查看插入的用户,然后使用
函数({console.log(“输入您的选择”)}
再次回调
我想我理解您的意思,编辑名为
save
的函数,在回调中传回保存的文档,例如
calkback(空,已保存)
。这样,您就不需要像您所暗示的那样绑定两个回调参数。
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();
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}