node.js变量是否为非阻塞

时间:2013-11-19 17:48:08

标签: node.js

我有一些节点代码,我试图设置它,但似乎它在另一个完成之前处理一个项目,我想知道我是否正确,如果是这样,如果有某种工作

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,这是可能的,它不会做任何其他执行,直到之前定义的一个完成所以我想知道节点是否有类似的东西,并注意我没有使用服务器或网站,我只是在我的电脑上测试代码。

3 个答案:

答案 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()