如何重新设置标准input后,我已经把它的标准输出?

你好,首先这个问题! 无论如何,我正在写一个小实验来帮助更好地把握stream和更复杂的结合stream和承诺的组合。

但是,我遇到了一个我目前无法解决的问题。 如果你运行我的下面的脚本,然后inputinput,然后按ctrl-d结束input:节点将尝试从标准input读取所需的,但因为标准input结束,立即closures。 那么有没有更好的方法来写这个? 或者有没有办法重置标准inputstream再次input? 还是有更好的方法来停止要求input等待结束事件来解决我的承诺?

同样值得注意的是:在Node 5.1.0上运行,使用ES2015(通过Babel 6)

import { Transform, Writable } from 'stream'; import util from 'util'; /** * Generic Transform * A test class to expiriment with creating a series of transforms * * @class * @extends {stream.Transform} */ class GenericTransform extends Transform { constructor (transformCallback, options={}) { super(Object.assign({}, options, { objectMode: true })); this._transformCallback = transformCallback; } /** * Transform * Stream method to transform read data, transform it, then move it to * the next stream. * * @method * @param {buffer} chunk - Buffer read from the input stream * @param {string} enc - Encoding of the input stream chunk buffer * @param {function} done - Callback to fire when transform is complete */ _transform (chunk, enc, done) { try { this.push(this._transformCallback(chunk, this)); done(); } catch (e) { this.emit('error', e); done(e); } } } /** * Stdout Writer * Handles writing to stdout including linebreaks. I believe this is * required as writing to the stdout stream will not emit end\finish events. * * @class * @extends {stream.Writable} */ class StdoutWriter extends Writable { constructor (options) { super(options); } /** * Write * Stream method to write to process.stdout * * @method * @param {buffer} chunk - Text that gets written to the console * @param {string} enc - Encoding of the buffer * @param {callback} done - Callback to call when finished */ _write (chunk, enc, done) { process.stdout.write(String(chunk) + '\n'); done(); } } /** * To * A shorthand function to create a generic transform method * * @method * @public * @param {function} transformer - transformer(data) returns new data * @returns {GenericTransform} A generic transform stream */ function to (transformer) { return new GenericTransform(transformer); } /** * Prompt * Requests input from the user then transforms it. Ideally it would ask for * input. When it receives a line it would stop reading, transform the data * then when the stream is finished ask the user for more input. * * @returns {Promise} A promise when the input has been read, transformed, * and displayed to the console via process.stdout.write */ function prompt () { process.stdout.write('Enter some input: '); return new Promise((resolve, reject) => { /** Start with process.stdin input stream */ process.stdin /** * Converts the raw string input into a simple object with * a contents property and a date property * * @example * > Test * > (ctrl-d) * {contents: "Test", date: 43993991013 } */ .pipe(to((chunk) => { return { contents: String(chunk).trim(), date: Date.now() }; })) /** * Takes the object created from the previous step and formats it as * a string using the inspect util. I suppose JSON.stringify would * also have worked. */ .pipe(to((obj) => { return util.inspect(obj); })) /** * Pipe to a writable stream that writes to stdout. This is necessary * because the docs say that stdout never emit finish or end events. */ .pipe(new StdoutWriter()) /** * Handle errors and finish events by either resolving or rejecting * the parent promise object. */ .on('finish', resolve) .on('error', reject); }); } /** Set the encoding so it all comes in as strings */ process.stdin.setEncoding('utf8'); /** * This is the main driver logic for connecting the above pieces. It will * input the first question then keeps asking for more input. To stop * entering data press ctrl-d to send an EOF to process.stdin. This * at least causes the finish event to fire at the end but on the next * usage of prompt, everything is done. */ prompt() .then(prompt);