我想做这样的事情
const { Readable } = require("stream");
function generatorToStream(generator) {
return new Readable({
read() {
(async () => {
for await (const result of generator()) {
if (result.done) {
this.push(null);
} else {
this.push(result.value);
}
}
})();
}
});
}
generatorToStream(async function*() {
const msg1 = await new Promise(resolve =>
setTimeout(() => resolve("ola amigao"), 2000)
);
yield msg1;
const msg2 = await new Promise(resolve =>
setTimeout(() => resolve("ola amigao"), 2000)
);
yield msg2;
const msg3 = await new Promise(resolve =>
setTimeout(() => resolve("ola amigao"), 2000)
);
yield msg3;
}).pipe(process.stdout);
但它不起作用,从来没有调用结束事件,并且我还没有在终端上收到任何数据。
任何解决方案或有关实现方法的提示吗?
答案 0 :(得分:0)
我是Scramjet的作者,该功能流处理框架可能对您来说是一个简单的解决方案。
如果您可以在项目中添加总共3个依赖项,那就再简单不过了:
const {StringStream} = require("scramjet");
StringStream.from(async function* () {
yield await something();
...
});
如果您想自己实现此功能,请查看DataStream line 112中的源代码-它应该很容易实现。通常,您需要实现以下内容:
function generatorToStream(gen) {
// obtain an iterator
const iter = await gen();
// create your output
const out = new Passthrough();
// this IIFE will do all the work
(async () => {
let done = false;
for await (let chunk of iter) {
// if write returns true, continue, otherwise wait until out is drained.
if (!out.write(chunk)) await new Promise((res, rej) => this.once("drain", res);
}
})()
// handle errors by pushing them to the stream for example
.catch(e => out.emit('error', e));
// return the output stream
return out;
}
上面的示例或多或少是在超燃冲压发动机中发生的事情-在保留较少的事件处理程序方面还有更多的优化措施,等等,但是上面的示例在简单的情况下应该能很好地工作。