如何包装一个节点`EventEmitter`,以将其作为终止的`AsyncIterator`使用?

时间:2019-11-20 18:30:52

标签: javascript node.js async-await generator ixjs

我正在尝试使用XML流解析API(xml-flow),该API公开一个节点EventEmitter,该节点为我感兴趣的标签发出一堆tag事件,并在完成阅读文档后发生end事件。

我希望能够使用Interactive Extensions进行修改,但是我不知道如何将其转换为异步可迭代的结尾; ix只有fromEvent / fromEventPattern似乎没有办法处理“结束”事件。

仅尝试:

import * as aix from 'ix/asynciterable';
import flow from 'xml-flow';

const iterTags = aix.fromEvent(flow(...), 'tag:foo');
console.log('max', aix.max(iterTags));

不产生任何输出,而添加.pipe(tap(console.debug))来打印要迭代的值,则表明流实际上已正确处理。

有没有一种方法可以连接end事件以使迭代器到达return,因此可以正常工作?

1 个答案:

答案 0 :(得分:2)

通过使用rxjs中的某些部分而不是相应的ixjs版本,我设法创建了一个异步可迭代的对象。

无论使用rxjs做什么,都可以始终从ix.from进行管道传输,以将可观察的转换为异步可迭代。

输入:

  <root>
      <foo>
        <name>Bill</name>
        <id>1</id>
        <age>27</age>
      </foo>
      <foo>
        <name>Sally</name>
        <id>2</id>
        <age>40</age>
      </foo>
      <foo>
        <name>Kelly</name>
        <id>3</id>
        <age>37</age>
      </foo>
    </root>

代码:

const {fromEvent} = require('rxjs');
const {takeUntil, tap, map} = require('rxjs/operators');
const ai = require('ix/asynciterable');

const [aiFrom, aiMax] = [ai.from, ai.max];


const flow = require('xml-flow');
const fs = require('fs');
const path = require('path');

const inFile = fs.createReadStream(path.join(__dirname, 'test.xml'));


const eventEmitter = flow(inFile);
const iterTags = aiFrom(
        fromEvent(eventEmitter, 'tag:foo')
            .pipe(takeUntil(fromEvent(eventEmitter, 'end')))
            .pipe(tap(console.log), 
                  map(o=>o.age))
    );


aiMax(iterTags).then((v)=>console.log("max age:", v));

// This works also
// (async()=>{
//     for await(el of iterTags){
//         console.log(el)
//     }
// })();

输出:

{ '$name': 'foo', name: 'Bill', id: '1', age: '27' }
{ '$name': 'foo', name: 'Sally', id: '2', age: '40' }
{ '$name': 'foo', name: 'Kelly', id: '3', age: '37' }
max age: 40