所以我在一个支持蓝牙的项目上使用了typescript/RXJS/React-Native;我有一个函数可以从给定的外围设备接收字符串,但是有一些警告是我无法在这个外围设备上避免的。
首先,它通过特定的命令模式与我通信;即,每个命令的形式都是/[a-zA-Z][^;]*;/
(也称为。一个字母字符,后面跟着任意数量的字符,以分号结尾)。
这些命令后面可能跟空格,也可能没有空格,这些空格应该被忽略。此外,这些命令可以串联发送,也可以不串联发送:a1234;bFGe4;
将是在同一消息中发送的两个命令a1234;
和bFGe4;
。但是,有一个警告:如果一个命令足够长,那么它可能是不完整的。例如,我可能收到两条消息c444a;X132124122412431
,然后是1234124;
,这两条消息应该被转换为两个单独的命令c444a;
和X1321241224124311234124;
。这是由于硬件限制造成的。
我设法使用一个可观察对象来处理这种情况,该对象将最后接收到的字符串的结尾保留在自身中:
const ANY_MSG = /[a-zA-Z][^;]*;/g
const messages$ = new Observable<string>(sub => {
let previousMsg = "";
// monitor messages is the function w/ a callback that receives messages from the device
monitorMessages((err, msg) => {
if (err) {
return sub.error(err);
}
const currMsg = previousMsg + msg
const matches = currMsg.match(ANY_MSG)
let lastIndex = 0
if(matches) {
for(const match of matches) {
sub.next(match)
lastIndex += match.length
}
}
previousMsg = currMsg.slice(lastIndex)
});
});
正如我所期望的那样,这个可观察对象发出我的消息:如果它们被monitorMessages
函数部分接收,则用分号分隔并连接起来。
问题是,我觉得这个函数很难阅读和理解,如果它是通过RXJS中的pipe
d函数组合的,那会更好。换句话说,我想这样做:
const messages$ = bindNodeCallback(monitorMessages).pipe(
// ??????
);
但是我不能确定我需要在那里应用哪些运算符(或者即使我需要编写自己的运算符),就像下面发生的那样:
monitorMessages
发出消息时,将其拆分为两部分:最后一个分号之前的部分和消息最后一个分号之后的部分monitorMessages
发出的命令,将存储的第二部分连接到新字符串,并使其经历与之前相同的过程
仅仅通过RXJS操作符就可以做到这一点吗?也许我需要创建一个新的可观察对象,作为第二部分的“存储”?我只是觉得当前的方法(为可观察对象创建某种内部状态)超级奇怪,并且相对难以理解atm。
发布于 2018-10-15 11:46:23
我认为你的实现很好。但是,如果您真的想使用运算符实现它,您可以使用scan
来维护组合的可观察链中的一些状态,如下所示:
const messages$ = bindNodeCallback(monitorMessages).pipe(
scan((acc, received) => {
const data = acc.remainder + received;
const messages = data.match(ANY_MSG);
if (messages) {
const length = messsages.reduce((total, message) => total + message.length, 0);
return { messages, remainder: data.slice(length) };
}
return { messages: [], remainder: data };
}, { messages: [], remainder: "" }),
mergeMap(({ messages }) => messages)
);
要发出消息数组,您可以使用mergeMap
,返回数组-因为数组就是ObservableInput
。
https://stackoverflow.com/questions/52805285
复制相似问题