我正在尝试创建一个函数,该函数返回连接的可写和可读流对。例如:
const { writable, readable } = createStreamPair();
与PassThrough流不同,每个端点具有正确的接口(writable instanceof stream.Readable === false
和readable instanceof stream.Writable === false
)。
用例:
createWriteStream(filePath) {
const { writable, readable } = createStreamPair();
writeFile(filePath, readable);
return writable;
}
如何创建我的createStreamPair()
函数?
编辑1
天真的方法显然行不通...
function createStreamPair() {
var readable = new stream.Readable();
var writable = new stream.Writable();
readable.pipe(writable);
return { writable, readable }
}
答案 0 :(得分:1)
Node.js测试使用一个函数,该函数创建两个双工流,可以从另一个中读取对一个的写入,反之亦然:https://github.com/nodejs/node/blob/master/test/common/duplexpair.js
它不是Node.js标准库的一部分,但是您可以编写自己的代码。
我将在此处显示一个经过稍微修改的带注释的版本:
const Duplex = require('stream').Duplex;
const assert = require('assert');
// Define some unique property names.
// The actual value doesn't matter,
// so long as they're not used by Node.js for anything else.
const kCallback = Symbol('Callback');
const kOtherSide = Symbol('Other');
// Define a function `DuplexSocket` whose prototype inherits from `Duplex`
class DuplexSocket extends Duplex {
constructor() {
// Let Node.js initialize everything it needs to
super();
// Define two values we will be using
// kCallback saves a temporary reference to a function while
this[kCallback] = null;
// kOtherSide will be the reference to the other side of the stream
this[kOtherSide] = null;
}
_read() {
// This is called when this side receives a push() call
// If the other side set a callback for us to call,
// then first clear that reference
// (it might be immediately set to a new value again),
// then call the function.
const callback = this[kCallback];
if (callback) {
this[kCallback] = null;
callback();
}
}
_write(chunk, encoding, callback) {
// This is called when someone writes to the stream
// Ensure there's a reference to the other side before trying to call it
assert.notStrictEqual(this[kOtherSide], null);
// Ensure that the other-side callback is empty before setting it
// If push immediately calls _read, this should never be a problem
assert.strictEqual(this[kOtherSide][kCallback], null);
// Let Node.js know when _read has been called
this[kOtherSide][kCallback] = callback;
// And finally, send the other side the data to be read
this[kOtherSide].push(chunk);
}
_final(callback) {
// Ask the other side to let us know it received our EOF request
this[kOtherSide].on('end', callback);
// And finally, pushing null signals the end of the stream
this[kOtherSide].push(null);
}
}
function makeDuplexPair() {
// Create two pairs of
const clientSide = new DuplexSocket();
const serverSide = new DuplexSocket();
// Set the other-side reference
clientSide[kOtherSide] = serverSide;
serverSide[kOtherSide] = clientSide;
// Both instances behave the same, so choice of name doesn't matter,
// So long as they're distinguishable.
return { clientSide, serverSide };
}
module.exports = makeDuplexPair;
这里是创建两个流的另一种方法,在这种情况下,一个是可读的,一个是可写的:
function makeAsymmetricalStreamPair() {
var readableCallback;
const readableSide = new ReadableStream;
readableSide._read = function _read(){
if(!readableCallback) return;
var callback = readableCallback;
readableCallback = null;
callback();
}
const writableSide = new WritableStream;
writableSide._write = function _write(chunk, enc, callback){
if(readableCallback) throw new Error;
if(typeof callback==='function') readableCallback = callback;
readableSide.push(chunk);
}
writableSide._final = function _final(callback){
readableSide.on('end', callback);
readableSide.push(null);
}
return { readableSide, writableSide };
}