我有一些节点代码,我试图设置它,但似乎它在另一个完成之前处理一个项目,我想知道我是否正确,如果是这样,如果有某种工作
var input = function(text){
process.stdout.write(text);
process.stdin.setEncoding('utf-8')
process.stdin.once("data", function(input_data){
return input_data;
}).resume();
}
var test = function(var1, var2){
var var1 = (var1 == null) ? input("Var One: ") : var1;
var var2 = (var2 == null) ? input("Var Two: ").split(" ") : var1;
console.log(var1, var2);
}
但是,当我执行test(null,null)
时,我希望它向我询问Var one
然后将var1
定义为数据,之后我认为它会提示我Var Two
然后通过空格将其拆分成一个列表,但这不起作用,它只是错误地说"Cannot call method of undefined "
我来自python,这是可能的,它不会做任何其他执行,直到之前定义的一个完成所以我想知道节点是否有类似的东西,并注意我没有使用服务器或网站,我只是在我的电脑上测试代码。
答案 0 :(得分:1)
我自己对节点很新,但这是我对它将如何执行的理解:
test(null, null);
// enter test() function
// see that var1 == null, run input("Var One: ")
// write "Var One: " to stdout
// set stdin encoding to utf-8
// set an event listener for 'data' on stdin, and provide a callback for that event
......让我们暂停一下,因为这是重要的一点。
当你设置一个监听器和一个回调时,你已经进入了异步性的土地。您的代码将继续前进而无需等待,并执行您告诉它要执行的下一步操作。在这种情况下,只是从input()
发回一个未定义的回报,然后继续处理var2
,同样地,你尝试调用undefined.split()
,整个过程都会发生。
另一方面,如果你只删除.split()
,你可能会得到这样的输出:
Var One: Var Two : [waiting for input]
此时,当你输入第一个值时,它会接受并将它从你的回调中返回到......无处...然后它会等待你的下一个值并做同样的事情。
这是你必须开始从你的python背景和程序性的同步习惯中脱离思想。
我冒险击败死马,并直接评论你的代码:
var input = function(text){
process.stdout.write(text);
process.stdin.setEncoding('utf-8')
// .once() is an asynchronous call
process.stdin.once("data", function(input_data){
// the return value of this anonymous function isn't used anywhere
return input_data;
}).resume();
// there is no return value of the "input" function
}
从功能上来说,你正在寻找的是类似下面的内容(虽然这很难看,像async.waterfall这样的结构让这种结构更加可口,并且可能有更好的方法可以做到这一点我没有'学到了):
function test(var1, var2) {
if (!var1 || !var2) {
process.stdin.resume();
process.stdin.setEncoding('utf-8');
if (!var1) {
process.stdout.write('Var One: ');
process.stdin.once('data', function(input_data) {
// var1 & var2 get pulled in from the parent context
var1 = input_data;
if (!var2) {
process.stdout.write('Var Two: ');
process.stdin.once('data', function(input_data) {
var2 = input_data;
console.log(var1, var2);
});
}
else {
console.log(var1, var2);
}
});
}
else if (!var2) {
process.stdout.write('Var Two: ');
process.stdin.once('data', function(input_data) {
var2 = input_data;
console.log(var1, var2);
});
}
else {
// there is no else, either var1 or var2 is missing
// per the first conditional
}
}
else {
console.log(var1, var2);
}
}
答案 1 :(得分:1)
以下是如何做到这一点:
function input (text, val, cb) {
if (val) return cb(null, val)
process.stdout.write(text)
process.stdin.setEncoding('utf-8')
process.stdin.once('data', function(data){
process.stdin.pause()
cb(null, data)
}).resume()
}
function test (var1, var2) {
input('Var One: ', var1, function (err, var1) {
input('Var Two: ', var2, function (err, var2) {
console.log(var1)
console.log(var2)
})
})
}
test(null, null)
基本上,由于stdin
是异步的,input
函数也是如此。您需要使用基于回调的函数样式。这很有效,但强烈建议您不要以这种方式使用stdin
。尝试使用readline
核心模块或来自npm的一些特殊用户态模块。
你可以看到编写基于回调的代码可能有点混乱(又称回调地狱)。下面是使用co
模块解决此问题的一种奇特方法(您需要节点0.11.x并使用--harmony-generators标志):
var co = require('co')
function input (text) {
return function (cb) {
process.stdout.write(text)
process.stdin.setEncoding('utf-8')
process.stdin.once('data', function(data){
process.stdin.pause()
cb(null, data)
}).resume()
}
}
function * test (var1, var2) {
var1 = var1 || (yield input('Var One: '))
var2 = var2 || (yield input('Var Two: '))
console.log(var1)
console.log(var2)
}
co(test)(null, null)
答案 2 :(得分:1)
我会使用这个内置的Node.js模块:http://nodejs.org/api/readline.html
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("What do you think of node.js? ", function(answer) {
// TODO: Log the answer in a database
console.log("Thank you for your valuable feedback:", answer);
rl.question("What do you think of JavaScript?", function(answer2) {
console.log("Answer2 is ", answer2);
});
rl.close();
});
从CoffeeScript派生出一种相对较新的语言,使异步代码更具可读性。它基本上看起来像同步代码,并且您不必一直为回调嵌套缩进。它叫做ToffeeScript https://github.com/jiangmiao/toffee-script来自Python你可能会很感激。
readline = require 'readline'
rl = readline.createInterface { input: process.stdin, output: process.stdout }
answer = rl.question! "What do you think of node.js?"
console.log "Thank you for your valuable feedback:", answer
answer2 = rl.question! "What do you think of ToffeeScript?"
console.log "Thanks again."
rl.close()