如何在没有 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'