2011-11-14 42 views
94

Tôi nghĩ để tạo một máy chủ http máy chủ đơn giản với một số tiện ích mở rộng bảng điều khiển. Tôi tìm thấy đoạn trích để đọc từ dữ liệu dòng lệnh.Giá trị đọc từ bảng điều khiển, tương tác

var i = rl.createInterface(process.stdin, process.stdout, null); 
    i.question('Write your name: ', function(answer) { 
    console.log('Nice to meet you> ' + answer); 
    i.close(); 
    process.stdin.destroy(); 

    }); 

cũng để đặt câu hỏi liên tục, tôi không thể sử dụng vòng lặp while(done) { }? Cũng tốt nếu máy chủ nhận được đầu ra tại thời điểm câu hỏi, nó làm hỏng dòng.

+1

Tôi giả định bởi 'rl' nghĩa là [readline] (https://stackoverflow.com/a/14513763/712526)? – jpaugh

Trả lời

109

bạn không thể thực hiện vòng lặp "while (done)" vì điều đó sẽ yêu cầu chặn trên đầu vào, điều mà node.js không thích làm.

Thay vì thiết lập một callback được gọi là mỗi lần một cái gì đó được nhập:

var stdin = process.openStdin(); 

stdin.addListener("data", function(d) { 
    // note: d is an object, and when converted to a string it will 
    // end with a linefeed. so we (rather crudely) account for that 
    // with toString() and then trim() 
    console.log("you entered: [" + 
     d.toString().trim() + "]"); 
    }); 
+1

Cảm ơn bạn điều này hoạt động, người nghe "kết thúc" có cho phép gọi một số hoạt động đóng và nói 'Tạm biệt' không? –

+0

Tôi đã xóa trình nghe "kết thúc" khỏi ví dụ, tôi không biết vị trí thực sự hữu ích khi thành thật. – rob

+0

cách kiểm soát dữ liệu đã nhập với câu lệnh if? hoặc swtich trường hợp? –

72

Tôi đã sử dụng một API cho mục đích này ..

var readline = require('readline'); 
var rl = readline.createInterface(process.stdin, process.stdout); 
rl.setPrompt('guess> '); 
rl.prompt(); 
rl.on('line', function(line) { 
    if (line === "right") rl.close(); 
    rl.prompt(); 
}).on('close',function(){ 
    process.exit(0); 
}); 

này cho phép để nhắc trong vòng lặp cho đến khi câu trả lời là right. Ngoài ra nó cung cấp cho giao diện điều khiển nhỏ đẹp.Bạn có thể tìm thấy các chi tiết @http://nodejs.org/api/readline.html#readline_example_tiny_cli

+5

Đây là một câu trả lời tuyệt vời. Điều có thể không rõ ràng (nhưng là một điểm cộng lớn) là readline không phụ thuộc vào bên ngoài: Đó là một phần của node.js. – jlh

22

API Readline đã thay đổi khá nhiều kể từ 12 '. Chương trình của doc một ví dụ hữu ích để nắm bắt đầu vào người dùng từ một dòng tiêu chuẩn:

const readline = require('readline'); 

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

rl.question('What do you think of Node.js? ', (answer) => { 
    console.log('Thank you for your valuable feedback:', answer); 
    rl.close(); 
}); 

More information here.

+2

đây chỉ là một ví dụ cơ bản. Làm thế nào để bạn tương tác? trả lời câu hỏi? nhiều lựa chọn và tương tự? Làm thế nào để mở lại rl một khi đóng cửa, nếu không thể làm thế nào để làm việc với rl mở để tương tác với người dùng bao gồm một số logic –

8

@ Rob câu trả lời sẽ làm việc hầu hết các lần, nhưng nó có thể không hoạt động như bạn mong đợi với sự đóng góp lâu.

Đó là những gì bạn nên sử dụng thay vì:

const stdin = process.openStdin(); 
let content = ''; 

stdin.addListener('data', d => { 
    content += d.toString(); 
}); 

stdin.addListener('end',() => { 
    console.info(`Input: ${content}`); 
}); 

Giải thích về việc tại sao giải pháp này hoạt động:

addListener('data') công trình như một bộ đệm, callback sẽ được gọi khi nó là đầy đủ hoặc/và kết thúc của đầu vào.

Điều gì về đầu vào dài? Một đơn gọi lại 'data' sẽ không đủ, do đó bạn sẽ nhận được phần tách đầu vào của mình trong hai hoặc nhiều phần. Điều đó thường không thuận tiện.

addListener('end') sẽ thông báo cho chúng tôi khi đọc stdin đọc xong đầu vào của chúng tôi. Vì chúng tôi đã lưu trữ dữ liệu trước đó, giờ đây chúng tôi có thể đọc và xử lý tất cả dữ liệu đó cùng nhau.

8

Vui lòng sử dụng readline-sync, điều này cho phép bạn làm việc với bảng điều khiển đồng bộ withouts callbacks hells. Ngay cả làm việc với mật khẩu:

var favFood = read.question('What is your favorite food? ', { 
 
    hideEchoBack: true // The typed text on screen is hidden by `*` (default). 
 
});

+0

Điều này đòi hỏi sự phụ thuộc thêm vì vậy tôi muốn các giải pháp khác. –

2

Tôi tin rằng đây xứng đáng là một câu trả lời async-await hiện đại, giả sử nút> = 7.x được sử dụng.

Câu trả lời vẫn sử dụng ReadLine::question nhưng kết thúc tốt đẹp để có thể đáp ứng được while (done) {}, đó là điều mà OP yêu cầu một cách rõ ràng.

var cl = readln.createInterface(process.stdin, process.stdout); 
var question = function(q) { 
    return new Promise((res, rej) => { 
     cl.question(q, answer => { 
      res(answer); 
     }) 
    }); 
}; 

và sau đó là một ví dụ sử dụng

(async function main() { 
    var answer; 
    while (answer != 'yes') { 
     answer = await question('Are you sure? '); 
    } 
    console.log('finally you are sure!'); 
})(); 

dẫn đến sau cuộc nói chuyện

Are you sure? no 
Are you sure? no 
Are you sure? yes 
finally you are sure! 
0

Một trường hợp sử dụng chung có lẽ sẽ cho ứng dụng để hiển thị một dấu nhắc chung chung và xử lý nó trong một báo cáo chuyển đổi.

Bạn có thể có được một hành vi tương đương với một vòng lặp while bằng cách sử dụng một hàm mà sẽ gọi chính nó trong callback:

const readline = require('readline'); 
const rl = readline.createInterface(process.stdin, process.stdout); 

function promptInput (prompt, handler) 
{ 
    rl.question(prompt, input => 
    { 
     if (handler(input) !== false) 
     { 
      promptInput(prompt, handler); 
     } 
     else 
     { 
      rl.close(); 
     } 
    }); 
} 

promptInput('app> ', input => 
{ 
    switch (input) 
    { 
     case 'my command': 
      // handle this command 
      break; 
     case 'exit': 
      console.log('Bye!'); 
      return false; 
    } 
}); 

Bạn có thể vượt qua một chuỗi rỗng thay vì 'app> ' nếu ứng dụng của bạn đã in một cái gì đó để màn hình bên ngoài vòng lặp này.

Các vấn đề liên quan