javascript - 如何在没有 Duplexer 包的情况下解决 NodeSchool 的 Duplexer 挑战

标签 javascript node.js stream duplex

问题(可从 nodeschool.io/#stream-adventure 下载)

Write a program that exports a function that spawns a process from a cmd string and an args array and returns a single duplex stream joining together the stdin and stdout of the spawned process. There is a very handy module you can use here: duplexer. The duplexer module exports a single function duplexer(writable, readable) that joins together a writable stream and readable stream into a single, readable/writable duplex stream.

官方解决方案

var spawn = require('child_process').spawn;
var duplexer = require('duplexer');

module.exports = function (cmd, args) {
    var ps = spawn(cmd, args);
    return duplexer(ps.stdin, ps.stdout);
}; 

此代码主要执行以下操作:

var spawn = require("child_process").spawn,
    Stream = require("stream");

module.exports = function (cmd, args) {
    var ps = spawn(cmd, args),
        stream = new Stream();
    stream.write = function (chunk, enc, cb) { ps.stdin.write(chunk, enc, cb); }
    stream.end = function (chunk, enc, cb) { ps.stdin.end(chunk, enc, cb); }
    ps.stdout.on("data", function (chunk) { stream.emit("data", chunk); });
    ps.stdout.on("end", function () { stream.emit("end"); });
    return stream;
}; 

没有双工器包的解决方案

我试图通过继承 Duplex 来解决问题类:

var spawn = require("child_process").spawn,
    Stream = require("stream");

require("util").inherits(Dx, Stream.Duplex);
function Dx(stdin, stdout) {
    Stream.Duplex.call(this);
    this.stdin = stdin;
    this.stdout = stdout;
}
Dx.prototype._write = function (chunk, enc, cb) { this.stdin.write(chunk, enc, cb); };
Dx.prototype._read = function (size) { return this.stdout.read(size); };

module.exports = function (cmd, args) {
    var ps = spawn(cmd, args),
        stream = new Dx(ps.stdin, ps.stdout);
    return stream;
};

当我测试这个 (stream-adventure verify program.js) 时,测试程序打印出 ACTUAL vs. EXPECTED 表(看起来正确),但在那之后它被卡住了。我的代码有什么问题?感谢您的帮助。

更新

添加这一行解决了问题:

Dx.prototype.end = function (chunk, enc, cb) { this.stdin.end(chunk, enc, cb); }

那么问题来了,为什么实现_read_write方法还不够呢?

最佳答案

process.stdin 在完成所有其他操作后仍然存在,这就是该过程不会结束的原因。要让进程结束,通常是方法process.stdin.pause()已使用,因为您可以在此之后恢复它。

您可以尝试覆盖 .end()方法,但这不是一个好的做法,更好的做法是:

#1 如果您知道要为此流写入的结束消息,您应该添加 .resume() ._write() 中的方法实现:

dstream._write = function (chunk, encoding, callback) {

    this.stdin.write(chunk, encoding, callback);

    if (someConditionToEnd) {
        this.stdin.pause();
    }
};

#2 收听结束事件:

/*
inside the stream prototype constructor
*/

this.on('end', function () {
    this.stdin.pause();
});

关于javascript - 如何在没有 Duplexer 包的情况下解决 NodeSchool 的 Duplexer 挑战,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23387960/

相关文章:

javascript - 解决对象数组的 Bluebird promise

javascript - 整数的正则表达式不产生结果

node.js - 如何在 node.js 流中与这个 <File> 对象交互?

c++ - stringstream::ignore(INT_MAX, '\n') 导致流失败

javascript - 在 Twilio 上使用一台设备进行多个连接

javascript - 类型错误 : undefined is not a function in javascript

javascript - 在 Javascript 中对以下字符串进行子字符串化的最简单方法

javascript - 将用户最后的语言偏好保存在 Cookie 中

node.js - 局域网通过webpack-dev-server访问 Node 服务器

c - 在C中向后读取文本文件