繁体   English   中英

Node.js 如何从 stream.Readable 同步读取行

[英]Node.js how to synchronously read lines from stream.Readable

我正在通过 stdio 与子进程交互,每次向 childProcess.stdin 写入一些命令时,我都需要等待来自 childProcess.stdout 的一行。
很容易包装一个异步方法来编写,如下所示:

async function write(data){
    return new Promise(resolve=>{
        childProcess.stdin.write(data,()=>resolve());
    })
}

但是,在读取时变得相当困难,因为来自标准输出的数据必须使用侦听器进行处理。 我在下面尝试过:

const LineReader = require("readline")
const reader = LineReader.createInterface(childProcess.stdout);
async function read(){
    return new Promise(resolve=>{
        reader.once("line",line=>resolve(line));
    })
}

但它总是返回第一行。
我知道我可以使用 setInterval 来实现这一点,而且我已经以这种方式实现了该功能。 但它显然对性能有影响,所以现在我试图通过将它包装成一个异步方法来优化它。
任何建议和解决方案将不胜感激!

好吧,我最终得到了与您尝试的非常相似的东西。 它做了一些代码中提到的假设,需要更完整的错误处理:

const cp = require('child_process');
const readline = require('readline');

const child = cp.spawn("node", ["./echo.js"]);
child.on('error', err => {
    console.log(err);
}).on('exit', () => {
    console.log("child exited");
});

const reader = readline.createInterface({ input: child.stdout });

// this will miss line events that occurred before this is called
// so this only really works if you know the output comes one line at a time
function nextLine() {
    return new Promise(resolve => {
        reader.once('line', resolve);
    });
}

// this does not check for stdin that is full and wants us to wait
// for a drain event
function write(str) {
    return new Promise(resolve => {
        let ready = child.stdin.write(str, resolve);
        if (!ready) {
            console.log("stream isn't ready yet");
        }
    });
}

async function sendCmd(cmd) {
    // get line reader event handler installed so there's no race condition
    // on missing the return event
    let p = nextLine();
    // send the command
    await write(cmd);
    return p;
}

// send a sequence of commands and get their results
async function run() {
    let result1 = await sendCmd("hi\n");
    console.log(`Got '${result1}'`);
    let result2 = await sendCmd("goodbye\n");
    console.log(`Got '${result2}'`);
    let result3 = await sendCmd("exit\n");
    console.log(`Got '${result3}'`);
}

run().then(() => {
    console.log("done");
}).catch(err => {
    console.log(err);
});

而且,出于测试目的,我使用这个 echo 应用程序运行它:

process.stdin.on("data", data => {
    let str = data.toString();
    let ready = process.stdout.write("return: " + str, () => {
        if (str.startsWith("exit")) {
            process.exit();
        }
    });
    if (!ready) {
        console.log("echo wasn't ready");
    }
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM