我有一个由sourceStream
个对象组成的BaseData
。
我想将此流转换为n
- 大量不同的流,然后根据自己的喜好过滤和转换每个BaseData
对象。
最后,我想让n
个流只包含特定类型,并且分叉流的长度可能不同,因为将来可能会丢弃或添加数据。
我以为我可以通过fork
:
import * as _ from 'highland';
interface BaseData {
id: string;
data: string;
}
const sourceStream = _([
{id: 'foo', data: 'poit'},
{id: 'foo', data: 'fnord'},
{id: 'bar', data: 'narf'}]);
const partners = [
'foo',
'bar',
];
partners.forEach((partner: string) => {
const partnerStream = sourceStream.fork();
partnerStream.filter((baseData: BaseData) => {
return baseData.id === partner;
});
partnerStream.each(console.log);
});
我预计现在有两个流,而foo
- 流包含两个元素:
{ id: 'foo', data: 'poit' }
{ id: 'foo', data: 'fnord' }
和bar
- 流包含一个元素:
{ id: 'bar', data: 'narf' }
然而我得到了一个错误:
/usr/src/marketing-tasks/node_modules/highland/lib/index.js:1338
throw new Error(
^
Error: Stream already being consumed, you must either fork() or observe()
at Stream._addConsumer (/usr/src/marketing-tasks/node_modules/highland/lib/index.js:1338:15)
at Stream.consume (/usr/src/marketing-tasks/node_modules/highland/lib/index.js:1500:10)
at Stream.each (/usr/src/marketing-tasks/node_modules/highland/lib/index.js:1774:18)
at partners.forEach (/usr/src/marketing-tasks/dist/bin/example.js:17:19)
at Array.forEach (native)
at Object.<anonymous> (/usr/src/marketing-tasks/dist/bin/example.js:12:10)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
如何将流分成多个流?
我也尝试过将这些电话联系起来,然后我才回复了一个流的结果:
partners.forEach((partner: string) => {
console.log(partner);
const partnerStream = sourceStream
.fork()
.filter((item: BaseData) => {
return item.id === partner;
});
partnerStream.each((item: BaseData) => {
console.log(item);
});
});
仅打印:
foo
{ id: 'foo', data: 'poit' }
{ id: 'foo', data: 'fnord' }
bar
而不是预期的:
foo
{ id: 'foo', data: 'poit' }
{ id: 'foo', data: 'fnord' }
bar
{id: 'bar', data: 'narf'}
也许我误解的是fork
就是这样的。根据{{3}}:
Stream.fork()分叉流,允许您添加其他使用者 共同的背压。分叉到多个消费者的流将 只能从最慢的消费者那里快速地从其来源拉取值 处理它们。
注意:不要依赖于分叉之间的一致执行顺序。 此转换仅保证所有forks都将处理值foo 在任何人将处理第二个值栏之前。它不保证 叉子处理foo的顺序。
提示:小心修改分支中的流值(或 使用这样做的库)。 由于将传递相同的值 每个fork,在一个fork中进行的更改将在任何fork中可见 在它之后执行。添加不一致的执行顺序,和 你最终可能会遇到细微的数据损坏错误。如果你需要修改 任何值,你应该复制并修改副本。
弃用警告:目前可以在之后分叉流 消费它(例如,通过变换)。这将不再可能 在下一个主要版本中。如果你要分叉流,总是 对它进行调用。
所以不是&#34;如何分叉流?&#34;我的实际问题可能是:如何将高地流动态复制到不同的流中?
答案 0 :(得分:1)
partnerStream.filter()
会返回新流。然后,您使用partnerStream
再次使用partnerStream.each()
,而不是调用fork()
或observe()
。因此,要么将partnerStream.filter().each()
调用链接起来,要么将partnerStream.filter()
的返回值分配给变量,并在其上调用.each()
。
答案 1 :(得分:0)
必须记住,在创建所有分支之前不要使用分叉流。好像一个人消费分叉流,它和它的父母&#34;将被消耗,使任何后续fork从空流中分叉。
const partnerStreams: Array<Stream<BaseData>> = [];
partners.forEach((partner: string) => {
const partnerStream = sourceStream
.fork()
.filter((item: BaseData) => {
return item.id === partner;
}
);
partnerStreams.push(partnerStream);
});
partnerStreams.forEach((stream, index) => {
console.log(index, stream);
stream.toArray((foo) => {
console.log(index, foo);
});
});
打印:
0 [ { id: 'foo', data: 'poit' }, { id: 'foo', data: 'fnord' } ]
1 [ { id: 'bar', data: 'narf' } ]