如何使用RxJS从arrayBuffer拆分数据框?

时间:2017-07-20 02:00:40

标签: javascript websocket rxjs observable rxjs5

我正在使用websocket从硬件接收数据帧。 数据框的定义如下:

0xbb(head) ---data--- 0xee(tail)

收到的数据存储在Uint8Array中,可能有多个框架:

var buffer = new Uint8Array([0xbb,0,0,0,0xee,0xbb,1,1,1,0xee,0xbb,3,3,3,0xee]);

我可以将数组转换为observable:

var obs= Rx.Observable.from(buffer);

RxMarbles:

--0xbb--0--0--0--0xee--0xbb--1--1--1--0xee--0xbb--2--2--2--0xee------
------------------000------------------111------------------222------

如何使用RxJS拆分可观察对象? 使用哪些运营商? RxJS是这种情况的最佳实践吗?

2 个答案:

答案 0 :(得分:2)

const source = Rx.Observable
  .from(['0xbb','0','0','0','0xee','0xbb','1','1','1','0xee','0xbb','3','3','3','0xee'])
  .concatMap(i => Rx.Observable.of(i).delay(1));

source
  .filter(i => i != '0xee' && i != '0xbb')
  .buffer(source.filter(i => i === '0xee'))
  .subscribe(val => console.log(val));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.2/Rx.js"></script>

我们需要使用concatMap(.. delay(1))将值转换为异步,否则缓冲区的closingNotifier运行速度比摄取值的速度快,最终得到三个空数组。但是,由于您从websocket接收这些数据包,因此您已经是异步。

此代码不是100%万无一失,例如当外部设备不发出0xee时会发生什么?我们最终将下一条消息连接到上一条消息。

答案 1 :(得分:2)

我认为你可以通过scan()实现你想要的目标:

const buffer = new Uint8Array([0xbb,0,0,0,0xee,0xbb,1,1,1,0xee,0xbb,3,3,3,0xee]);
const obs = Observable.from(buffer);

obs.scan((acc, v) => {
    if (v === 0xbb) {
      return [v];
    } else {
      acc.push(v);
      return acc;
    }
  }, [])
  .filter(acc => acc[acc.length - 1] === 0xee)
  .subscribe(console.log);

这将打印以下数组:

[ 187, 0, 0, 0, 238 ]
[ 187, 1, 1, 1, 238 ]
[ 187, 3, 3, 3, 238 ]

但是,如果您需要为每个数据框发出Observable,请按照Mark的回答,使用window()代替buffer()