【问题标题】:How to solve NodeSchool's Duplexer challenge without the Duplexer package如何在没有 Duplexer 包的情况下解决 NodeSchool 的 Duplexer 挑战
【发布时间】:2014-06-16 18:23:24
【问题描述】:

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

编写一个导出函数的程序,该函数从 cmd 字符串和 args 数组并返回单个双工流 将生成的进程的标准输入和标准输出连接在一起。有 您可以在这里使用一个非常方便的模块:双工器。双工器模块 导出连接的单个函数duplexer(writable, readable) 将可写流和可读流合并为一个, 可读/可写双工流。

官方解决方案

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;
}; 

没有 Duplexer 包的解决方案

我尝试通过继承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 方法还不够?

【问题讨论】:

  • “卡住”是什么意思?进程没有结束?还是发生了其他事情?
  • 是的。打印表格后,测试程序“冻结”(我的意思是,它不做任何事情)。更新:原来end 方法丢失了。

标签: javascript node.js stream duplex


【解决方案1】:

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

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

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

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();
});

【讨论】:

    猜你喜欢
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 2021-09-07
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多