首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >rxjs运算符,用于从源收集字符串并根据模式部分发出它们

rxjs运算符,用于从源收集字符串并根据模式部分发出它们
EN

Stack Overflow用户
提问于 2018-10-15 01:34:18
回答 1查看 195关注 0票数 1

所以我在一个支持蓝牙的项目上使用了typescript/RXJS/React-Native;我有一个函数可以从给定的外围设备接收字符串,但是有一些警告是我无法在这个外围设备上避免的。

首先,它通过特定的命令模式与我通信;即,每个命令的形式都是/[a-zA-Z][^;]*;/ (也称为。一个字母字符,后面跟着任意数量的字符,以分号结尾)。

这些命令后面可能跟空格,也可能没有空格,这些空格应该被忽略。此外,这些命令可以串联发送,也可以不串联发送:a1234;bFGe4;将是在同一消息中发送的两个命令a1234;bFGe4;。但是,有一个警告:如果一个命令足够长,那么它可能是不完整的。例如,我可能收到两条消息c444a;X132124122412431,然后是1234124;,这两条消息应该被转换为两个单独的命令c444a;X1321241224124311234124;。这是由于硬件限制造成的。

我设法使用一个可观察对象来处理这种情况,该对象将最后接收到的字符串的结尾保留在自身中:

代码语言:javascript
复制
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中的piped函数组合的,那会更好。换句话说,我想这样做:

代码语言:javascript
复制
const messages$ = bindNodeCallback(monitorMessages).pipe(
  // ??????
);

但是我不能确定我需要在那里应用哪些运算符(或者即使我需要编写自己的运算符),就像下面发生的那样:

  • 每当monitorMessages发出消息时,将其拆分为两部分:最后一个分号之前的部分和消息最后一个分号之后的部分
  • 发出第一部分中所有以分号分隔的命令,并再次存储第二个part
  • Whenever monitorMessages发出的命令,将存储的第二部分连接到新字符串,并使其经历与

之前相同的过程

仅仅通过RXJS操作符就可以做到这一点吗?也许我需要创建一个新的可观察对象,作为第二部分的“存储”?我只是觉得当前的方法(为可观察对象创建某种内部状态)超级奇怪,并且相对难以理解atm。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-15 11:46:23

我认为你的实现很好。但是,如果您真的想使用运算符实现它,您可以使用scan来维护组合的可观察链中的一些状态,如下所示:

代码语言:javascript
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52805285

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档