带状态的 ifElse 语句?

ifElse statement with state?

背景

我正在制作一个从多个设备接收消息的应用程序。收到消息后,将使用给定消息触发事件:

on( "data", message => {
    //doSomething
} );

挑战

此函数接收两种类型的消息:A 和 B:

我处理这个问题的第一个方法如下:

const { ifElse } = require("ramda");

const evalData = ifElse(
    isTypeA,        // Returns true if type A, false otherwise
    evalTypeA,      // Returns device Id
    evalTypeB       // Processes data in message and returns bytes read
);

on( "data", evalData );

问题

这里的问题是类型 B 的消息没有它们所属设备的 ID。因此,为了正确处理消息,我需要 evalTypeA 在上一条消息中返回的 deviceId。

我解决这个问题的想法是将 Id 传递给 evalTypeB:

const evalData = messages => {
    let id = undefined;
    id = ifElse(
        isTypeA,        // Returns true if type A, false otherwise
        evalTypeA,      // Returns device Id
        evalTypeB( id )       // Processes data in message and returns bytes read
    )( message );
} 

这里的问题是这行不通! evalTypeB 也是 returns 一个数字,然后我不知道 ifElse 表达式给我的是读取的字节数还是 Id!

问题

在没有突变和副作用的情况下,你如何解决这个问题?

根据定义,作为 on('data', callback) 的回调被重复调用的纯函数无法跟踪先前调用的状态。

考虑到这一点,有几个选项可供考虑,以帮助尽量减少或限制副作用:

  1. 关闭状态,保持逻辑没有副作用:
const processMsg = ifElse(isTypeA, evalTypeA, evalTypeB)

const handler = initialState => {
  let state = initialState
  return msg => {
      state = processMsg(state, msg)
  }
}

on('data', handler(42))
  1. 递归附加一个新的处理程序,在每次调用结束时只为每条消息调用一次,将效果限制在处理程序注册中(假设事件发射器支持 once 之类的东西) :
const processMsg = ifElse(isTypeA, evalTypeA, evalTypeB)

const handler = state => msg =>
  once('data', handler(processMsg(state, msg)))

once('data', handler(42))