如何从observable获取第一个元素并为流的其余部分返回一个observable?

时间:2017-08-18 16:16:25

标签: javascript rxjs reactive

我试图写一个Observable来从CSV文件中返回对象。我的问题是我想使用文件的标题,用作Observer的下一个元素的属性名称。例如,如果我有这个CSV:

symbol;word
1;one
2;two
3;three

我希望这种情况发生:

getObjects().subscribe(o => console.log(o));

// should log this:
{ symbol: '1', word: 'one' }
{ symbol: '2', word: 'two' }
{ symbol: '3', word: 'three' }

我设法使用此代码执行此操作:

const Rx = require('rxjs/Rx');
const _zipObject = require('lodash/zipObject');

const getObjects = () => {
    const observable = Rx.Observable.of(
        ['symbol', 'word'],
        ['1', 'one'],
        ['2', 'two'],
        ['3', 'three']
    ).share();

    let header;

    return Rx.Observable.concat(
        observable.first().do(line => header = line).filter(() => false),
        observable.skip(1).map(line => _zipObject(header, line))
    );
};

getObjects().subscribe(o => console.log(o));

它有效,但并不好看。我还考虑过使用过滤器来过滤第一个元素并设置标题,但它感觉不会好多了,而且还有一个缺点就是为每个元素调用过滤器回调。

1 个答案:

答案 0 :(得分:1)

您可以使用combineLatest同时获取标题和日期,并避免从父作用域访问它:

const Rx = require('rxjs/Rx');
const Observable = Rx.Observable;

const getObjects = () => {
    const observable = Observable.of(
        ['symbol', 'word'],
        ['1', 'one'],
        ['2', 'two'],
        ['3', 'three']
    ).share();

    const header$ = observable.take(1);
    const data$ = observable.skip(1);

    return Observable.combineLatest(header$, data$, (headers, line) => {
        const result = {};
        headers.forEach((header, i) => {
            result[header] = line[i];
        });

        return result;
    });
};

getObjects().subscribe(o => console.log(o)); 

打印:

{ symbol: '1', word: 'one' }
{ symbol: '2', word: 'two' }
{ symbol: '3', word: 'three' }