0

我正在玩弄Q立即尝试按顺序要求用户输入一些内容。例如 :

What is your name? Bob
What is your age? 40
Hello Bob (40)! 

(是的!这是一个简单的“Hello world!”程序。)

这是我正在尝试的代码,直接来自 Q 的 github 项目页面:

Q.fcall(promptly.prompt, "What is your name? ")
.then(promptly.prompt, "What is your age? ")
.done(function(name, age) {            
  console.log("Hello " + name + " (" + age + ")");
});

});

但它没有按预期工作(也许我读错了?)。无论我尝试什么,似乎promptly.prompt都是在并行听击键,并且.done立即调用该函数,从而导致

/path/to/node_modules/promptly/index.js:80
         fn(null, data);
         ^
TypeError: undefined is not a function
     at /path/to/node_modules/promptly/index.js:80:9
     ...

一旦我击中Enter。知道为什么这样做以及如何完成我想做的事情吗?

** 编辑 **

基本上,我的最终目标是创建一个像这样调用的可重用函数:

promptAll({ 
    'name': "What is your name? ", 
    'age': "What is your age? "
}).done(function(input) {
    console.log(input);  // ex: { name: "Bob", age: 40 }
});

** 更新 **

这是我的工作解决方案,我必须按照WiredPrainenfcall的建议使用:

function multiPrompt(args) {
  function _next() {
    if (keys.length) {
      var key = keys.pop();
      Q.nfcall(promptly.prompt, args[key]).done(function(value) {
        result[key] = value;
        _next();
      });
    } else {
      def.resolve(result);
    }
  };
  var def = Q.defer();  
  var keys = _.keys(args).reverse();
  var result = {};

  _next();

  return def.promise;
};

注意:我使用的是下划线,但同样可以使用标准对象迭代器来实现。)

4

2 回答 2

2

以下是两种方法。

首先,您需要nfcall使 Q 使用 NodeJS 的回调约定。

但是,由于函数不是承诺,您需要稍微不同地处理链接和同步行为。

在第一个示例中start1,代码创建 的实例defer并将其作为承诺返回。当prompt函数返回时,它resolve是延迟对象实例并传递value函数的 (理想情况下是提示符)。它还应该处理“真实”代码中的错误等。

在这两个示例中,我都添加了一个函数来获取 promise 解析的结果。它不会作为参数传递给最后一个done实例。传递给的函数done将在第一个 Promise 解决后立即执行(prompt在这种情况下返回之后)。

var promptly = require('promptly');
var Q = require('q');

// make a simple deferred/promise out of the prompt function
var prompter = function(text) {
    var deferred = Q.defer();

    promptly.prompt(text, function(err, value) {
       deferred.resolve(value);
    });

    return deferred.promise;
};

// this option just uses the promise option to prompt for name.
function start1() {
    prompter("What is your name?").then(function(name) {
        prompter("Your age?").then(function(age) {
            console.log("Hello " + name + " (" + age + ")");
        });
    });
}

// this one uses the nfcall funcitonality to directly call the 
// promptly.prompt function (and waits for a callback).
function start2() {
    Q.nfcall(promptly.prompt, "What is your name? ")
        .then(function(name) {
                Q.nfcall(promptly.prompt, "What is your age? ")
                    .done(function(age) {
                        console.log("Hello " + name + " (" + age + ")");
                    });
        });
}

//start1();
于 2013-10-06T16:12:28.110 回答
1

我觉得这里的答案可以添加到任何寻求替代方案来解决从节点获取命令行用户输入的一般问题的人。

首先,我个人认为转向 ES6 Promises API 是有好处的。虽然 Node 中还没有原生可用,但有一个很棒的 polyfill:https ://github.com/jakearchibald/es6-promise 。

其次,我开始喜欢另一个用户提示模块:https ://github.com/flatiron/prompt

现在假设存在依次返回承诺的方法“addUserToDb”、“printUser”和“printError”,以下示例是可能的:

var prompt = require('node-prompt');
var Promise = require('es6-promise').Promise;

var promptUser = function(schema) {
  return new Promise(resolve, reject) {
    prompt.get(schema, function(err, result) {
      if (err) {
        reject(err);
      } else {
        resolve(result);
      }
    });
  };
};

promptUser(["name", "password"])
  .then(addUserToDb)
  .then(printUser)
  .catch(printError)

我现在使用这种方法编写了许多“脚本”,并且发现它非常好用并且易于维护/适应。

于 2014-02-19T15:31:23.623 回答