2014-04-03 42 views
3

我试图编写一个脚本,在一行中询问三个问题,同时等待每个问题之间的用户输入。
看来我很难理解如何用节点的非阻塞性质来做到这一点。
这里是我运行代码:使用Nodejs的多个用户输入

var shell = require('shelljs/global'), 
    utils  = require('./utils'), 
    readline = require('readline'), 
    fs  = require('fs'), 
    path  = require('path'); 

var rl = readline.createInterface({ 
    input: process.stdin, 
    output: process.stdout 
});  

setUserDefaultSettings(); 

function setUserDefaultSettings() { 
    var defaultSettingsFile = find('DefaultSettings.json'); 
    var defaultSettingsJSON = [ 
     { 
      macro: '__new_project_path__', 
      question: 'Please enter the destination path of your new project: ' 
     }, 
     { 
      macro: '__as_classes_path__', 
      question: 'Please enter the path to your ActionScript Classes: ', 
     }, 
     { 
      macro: '__default_browser_path__', 
      question: 'Please enter the path to your default browser: ' 

     } 
    ]; 
    var settingsKeys = []; 
    var index  = 0; 

    if (!test('-f', 'UserSettings.json')) { 
     cp(defaultSettingsFile, 'UserSettings.json'); 
    } 

    var userSettingsFile = pwd() + path.sep + find('UserSettings.json'); 

    fs.readFile(userSettingsFile, 'utf8', function (err, data) { 
     if (err) { 
      echo('Error: ' + err); 
      return; 
     } 
     data = JSON.parse(data); 

     for(var attributename in data) { 
      settingsKeys.push(attributename); 
     } 

     defaultSettingsJSON.forEach(function(key) { 
      index++; 
      // Check if macros have been replaced 
      if (data[settingsKeys[index - 1]] === key.macro) { 
       // Replace macros with user input. 
       replaceSettingMacro(userSettingsFile, key.macro, key.question); 
      } 
     }); 
    }); 
} 

function replaceSettingMacro(jsonFile, strFind, question) { 
    askUserInput(question, function(strReplace) { 
     sed('-i', strFind, strReplace, jsonFile); 
    }); 
} 

function askUserInput(string, callback) { 
    rl.question(string, function(answer) { 
     fs.exists(answer, function(exists) { 
      if (exists === false) { 
       echo('File ' + answer + ' not found!'); 
       askUserInput(string, callback); 
      } else { 
       callback(answer); 
      } 
     }); 
    }); 
} 

只有第一个问题是问,作为脚本继续执行,而在用户输入他们的答案。我明白为什么会出现这种情况,但不知道如何解决这个问题。

+0

您是否尝试过的回调? – c0d3junk13

回答

2

这看起来像是一个实现队列的适当位置。队列将在前一个完成后开始下一个任务。

在askUserInput方法你可以试试:

var questionQueue = []; 
function askUserInput(string, callback) { 
    if(questionQueue.length == 0) { 
     rl.question(string, function(answer) { 
      fs.exists(answer, function(exists) { 
       if (exists === false) { 
        echo('File ' + answer + ' not found!'); 
        askUserInput(string, callback); 
       } else { 
        callback(answer); 

        if(questionQueue.length > 0){ 
         var question questionQueue.shift(); 
         askUserInput(question.string, question.callback); 
        } 
       } 
      }); 
     }); 
    } 
    else { 
     questionQueue.push({string: string, callback: callback}); 
    } 
} 

另一个选项中包括进一步延长了回调调用堆栈,当你从以前接受回调调用下一个问题。

+1

谢谢,我已经设法找到答案,同时遵循排队和回调的建议。我刚写下我的解决方案作为一个职位。 – caubry

2

2种方式我会处理这个问题:
一)使用sync-prompt - 将使它很容易

如果你仍想以异步方式处理它,
B)我会使用一个承诺库等作为When并做一个When.all([array of promises])继续之前。

+0

我发现模块和库非常有趣,有用且易于使用。绝对是我将来会用到的东西。然而,就这个问题而言,我认为正确的解决方法是普雷斯顿引用的解决方法。 – caubry

0

下面才是正确的解决我的问题,以下@普雷斯顿-S建议:

var questionList = []; 
var macroList = []; 

setUserDefaultSettings(); 

function setUserDefaultSettings() { 
    var defaultSettingsFile = find('DefaultSettings.json'); 
    var defaultSettingsJSON = [ 
     { 
      macro: '__new_project_path__', 
      question: 'Please enter the destination path of your new project: ' 
     }, 
     { 
      macro: '__as_classes_path__', 
      question: 'Please enter the path to your ActionScript Classes: ', 
     }, 
     { 
      macro: '__default_browser_path__', 
      question: 'Please enter the path to your default browser: ' 

     } 
    ]; 

    if (!test('-f', 'UserSettings.json')) { 
     cp(defaultSettingsFile, 'UserSettings.json'); 
    } 

    userSettingsFile = pwd() + path.sep + find('UserSettings.json'); 

    var settingsKeys  = []; 
    var index   = 0; 
    var canAskQuestion = false; 

    fs.readFile(userSettingsFile, 'utf8', function (err, data) { 
     if (err) { 
      echo('Error: ' + err); 
      return; 
     } 
     data = JSON.parse(data); 

     for(var attributename in data) { 
      settingsKeys.push(attributename); 
     } 

     defaultSettingsJSON.forEach(function(key) { 
      index++; 
      // Check if macros have been replaced 
      if (data[settingsKeys[index - 1]] === key.macro) { 
       // Replace macros with user input. 
       questionList.push(key.question); 
       macroList.push(key.macro); 

       if (!canAskQuestion) { 
        askQuestion(function() { 
         copyTemplate(); 
        }); 
        canAskQuestion = true; 
       } 
      } else { 
       copyTemplate(); 
      } 
     }); 
    }); 
} 

function askQuestion(callback) { 
    replaceSettingMacro(userSettingsFile, macroList.shift(), questionList.shift(), function() { 
     if (macroList.length < 1 || questionList.length < 1) { 
      callback(); 
     } else { 
      askQuestion(callback); 
     } 
    }); 
} 

function replaceSettingMacro(jsonFile, strFind, question, callback) { 
    askUserInput(question, function(strReplace) { 
     sed('-i', strFind, strReplace, jsonFile); 
     callback(); 
    }); 
} 

function askUserInput(string, callback) { 
    rl.question(string, function(answer) { 
     fs.exists(answer, function(exists) { 
      if (exists === false) { 
       echo('File ' + answer + ' not found!'); 
       askUserInput(string, callback); 
      } else { 
       callback(answer); 
      } 
     }); 
    }); 
} 

function copyTemplate() { 
    rl.close(); 
}