运算符多次为合并的Observable调用,尽管只有一个源发出

时间:2018-05-16 14:01:32

标签: node.js typescript rxjs rxjs5

我有一个函数,我正在调用Manager的{​​{1}}实例,我正在订阅它以更新我的应用程序的状态(我正在管理一个状态服务器端也是如此。

问题在于onSpecificData()的{​​{1}}实现我使用SomeManager运算符合并了3个不同的onSpecificData()运算符,由于某种原因触发了调用所有潜在的Observable运算符中的运算符,即使只有一个源是发出值的运算符

SomeManager.ts

merge()

Manager.ts

Observable

SomeDriver.ts

export class DerivedManager implements Manager {
    private driver: SomeDriver;

    constructor(...) {
        this.driver = new SomeDriver(...);
    }

    public onSpecificData(): Observable<DataType> {
        return merge(
            this.driver.onSpecificData(Sources.Source1).map((value) => {
                return {source1: value};
            }),
            this.driver.onSpecificData(Sources.Source2).map((value) => {
                return {source2: value};
            }),
            this.driver.onSpecificData(Sources.Source3).map((value) => {
                return {source3: value};
            })
        );
    }

Driver.ts

export type DataType = Partial<{value1: number, value2: number, value3: number}>;

export interface Manager {
    onSpecificData(): Observable<DataType>;
}

Handler.ts

export const enum Sources {
    Source1,
    Source2,
    Source3,
}

export class SomeDriver extends Driver {
    private static specificDataId = 1337; // some number

    private handler: Handler;

    constructor(...) {
        super(...);
        this.handler = new Handler(this.connection, ...);
        // ...
    }

    // ...

   onSpecificData(source: Sources): Observable<number> {
       return this.handler
           .listenToData<SpecificDataType>(
               SomeDriver.specificDataId,
               (data) => data.source === source)
           ).map((data) => data.value);
   }
}

最后,export abstract class Driver { protected connection: Duplex; constructor(...) { // init connection, etc... } public abstract onSpecificData(source: number); // some implementations and more abstract stuff... } - ing:

export class Handler {
    private data$: Observable<Buffer>;

    constructor(private connection: Duplex, ...) {
        this.data$ = Observable.fromEvent<Buffer>(connection as any, 'data');
    }

    listenToData<T>(dataId: number, filter?: (data: T) => boolean) {
        return this.data$
            .map((data) => {
                 // decode and transform
            })
            .filter((decodedData) => !decodedData.error && decodedData.value.id)
            .do((decodedData) => {
                 console.log(`Got ${decodedData.value.id}`);
            })
            .map((decodedData) => decodedData.value.value as T)
            .filter(filter || () => true);
    }
}

正如您所看到的,只有 1 基础subscribe()export default function(store: Store<State>, manager: Manager) { // ... manager.onSpecificData() .subscribe((data) => { // update state according to returned data }); } ),但显然Observable中的运算符链被调用 3 < / strong>次为其发出的每个值。我已经知道这是因为data$ {3} listenToData<T>()中的SomeManager#onSpecificData(),但我不知道为什么会这样。我希望每个值都调用一次。

非常感谢帮助。

1 个答案:

答案 0 :(得分:0)

我在&#34; hacky&#34;中解决了这个问题。在我看来,方式。我将data$替换为Subject,从stream 'data'事件中创建了一个observable,将所有共享逻辑移动到该observable并从中发出一个值主题,像这样:

export class Handler {
    private dataSrc = new Subject<DecodedData>();

    constructor(private connection: Duplex, ...) {
        Observable.fromEvent<Buffer>(connection as any, 'data')
            .map((data) => {
                 // decode and transform
            })
            .filter((decodedData) => !decodedData.error)
            .do((decodedData) => {
                 console.log(`Got ${decodedData.value.id}`);
            })
            .subscribe((decodedData) => {
                this.dataSrc.next(decodedData);
            });
    }

    listenToData<T>(dataId: number, filter?: (data: T) => boolean) {
        return this.dataSrc
            .filter((decodedData) => decodedData.value.id === dataId)
            .map((decodedData) => decodedData.value.value as T)
            .filter(filter || () => true);
    }
}

不完全是我正在寻找的解决方案,但它确实有效。如果有人有更好的解决方案,更适合&#34; Rx方式&#34;要做的事情,我很乐意听到它。