将缓冲区分解为rxjs大小

时间:2018-08-15 16:51:06

标签: javascript rxjs observable rxjs6

我每次都有一个可观察到的从流中获取数据,大小分别为512,我必须将其分解为其他可观察到的200个字符,并将[12] char保留在其他缓冲区中以与下一个块连接,我使用新主题和for循环,我相信可能会有更好,更漂亮的解决方案。

可观察到的----------------------------------------

  • 下一个第一[512] -------> [112] [200] [200] -------> [200] [200]
  • 第二个下一个[512] [ 112 ]-> [24] [200] [200] [88+ 112 ]-> [200] [200 ]
  • 下一个第三[512] [24]-> [136] [200] [76 + 124] .....
  • 第n次迭代[512] [194]-> [106] [200] [200] [106 + 94]-> [200] [200] [200]

  • 第n + 1个[512] [6] .......

maxValueSize = 200
this._sreamRecord$.subscribe(
    {
        next: (val) => {
            const bufferToSend: Buffer = Buffer.concat([completationBuffer, val])
            for (let i = 0; i < bufferToSend.length; i += maxValueSize) {
                if (bufferToSend.length - i > maxValueSize) {
                    bufferStreamer.next(bufferToSend.slice(i, i + maxValueSize))
                } else {
                    completationBuffer = bufferToSend.slice(i, i + maxValueSize)
                }
            }
        },
        complete() {
            if (completationBuffer.length) {
                bufferStreamer.next(completationBuffer)
            }
            bufferStreamer.complete()
        }
    })

1 个答案:

答案 0 :(得分:0)

您可能需要考虑以下解决方案

const splitInChunksWithRemainder = (remainder: Array<any>) => {
    return (streamRecord: Array<any>) => {
        const streamRecordWithRemainder = remainder.concat(streamRecord);
        let chunks = _.chunk(streamRecordWithRemainder, maxValueSize);
        const last = chunks[chunks.length - 1];
        let newRemainder = [];
        if (last.length != maxValueSize) {
            newRemainder = chunks[chunks.length - 1];
            chunks.length = chunks.length - 1;
        }
        return {chunks, newRemainder};
    };
}

let f = splitInChunksWithRemainder([]);

this._sreamRecord$.pipe(
    switchMap(s => {
        const res = f(s);
        f = splitInChunksWithRemainder(res.newRemainder);
        return from(res.chunks);
    })
)
.subscribe(console.log);

这个想法是在连接上一个 remainder 后,用streamRecord lodash函数分割每个chunk,即从前一个streamRecord

这是通过函数splitInChunksWithRemainder完成的,该函数是更高级别的函数,即在返回remainder的情况下返回函数的函数来自上一个拆分。

评论后更新

如果您还需要发出 last newRemainder,则可以考虑以下更复杂的解决方案

const splitInChunksWithRemainder = (remainder: Array<any>) => {
    return (streamRecord: Array<any>) => {
        const streamRecordWithRemainder = remainder.concat(streamRecord);
        let chunks = _.chunk(streamRecordWithRemainder, maxValueSize);
        const last = chunks[chunks.length - 1];
        let newRemainder = [];
        if (last.length != maxValueSize) {
            newRemainder = chunks[chunks.length - 1];
            chunks.length = chunks.length - 1;
        }
        return {chunks, newRemainder};
    };
}

const pipeableChain = () => (source: Observable<any>) => {
    let f = splitInChunksWithRemainder([]);
    let lastRemainder: any[];
    return source.pipe(
        switchMap(s => {
            const res = f(s);
            lastRemainder = res.newRemainder;
            f = splitInChunksWithRemainder(lastRemainder);
            return from(res.chunks);
        }),
        concat(defer(() => of(lastRemainder)))
    )
}

_streamRecord$.pipe(
    pipeableChain()
)
.subscribe(console.log);

我们引入了pipeableChain函数。在此函数中,我们保存通过执行splitInChunksWithRemainder返回的余数。源Observable完成后,我们将通过concat运算符添加最后一个通知。 如您所见,我们还必须使用defer运算符来确保仅在观察者订阅时(即在源Observable完成之后)创建Observable。如果没有defer,则在最初订阅源Observable时(即,当concat仍未定义时)将创建作为参数传递给lastRemainder的Observable。