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

Posted

技术标签:

【中文标题】如何在没有 Duplexer 包的情况下解决 NodeSchool 的 Duplexer 挑战【英文标题】:How to solve NodeSchool's Duplexer challenge without the Duplexer package 【发布时间】: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 方法丢失了。 【参考方案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();
);

【讨论】:

以上是关于如何在没有 Duplexer 包的情况下解决 NodeSchool 的 Duplexer 挑战的主要内容,如果未能解决你的问题,请参考以下文章

Python错误“ImportError: No module named MySQLdb”解决方法

Python-在没有网络的情况下pip超时无法下载包时解决包的安装

如何在没有包的情况下真正获得类的名称?

Error in library(e1071) : there is no package called 'e1071'

python No module named找不到自己写的模块 3种情况及解决方法

ModuleNotFoundError: No module named ‘exceptions‘ 情况解决