以功能性方式正确处理状态和WebSockets 编辑

问题描述

这是一个较大项目的一部分,我在其中重写了多人游戏的命令性代码以使其正常运行。现在,我或多或少地是从一开始就试图从高层次思考结构。这就是我的想法:

弥合命令功能鸿沟的部分是此类:

class MessageStream<T> {
  private readonly actions: T[] = []
  private popResolvers: ((value: T) => void)[] = []

  push(value: T) {
    this.actions.push(value)
    if (this.popResolvers.length > 0) {
      this.popResolvers.shift()(this.actions.shift())
    }
  }

  pop(): Promise<T> {
    return new Promise<T>((resolve) => {
      if (this.actions.length > 0 && this.popResolvers.length === 0) {
        resolve(this.actions.shift())
      } else {
        this.popResolvers.push(resolve)
      }
    })
  }
}

我像这样启动Web服务器:

const server = new WebServer.Server({ port: 3000 })
const messageStream = new MessageStream<string>()
const initialState: State  = { letters: "a" }

server.on("connection",(socket) => {
  socket.on("message",(data) => {
    try {
      messageStream.push(data.toString())
    } catch (error) {
      console.log("[Error index.ts]",error)
    }
  })
})

这是状态更新逻辑要去的地方:

const handle = async (stream: MessageStream<string>,state: State) => {
  const action = await stream.pop()
  // do some other thinking to update the state,such as:
  handle(stream,{ letters: state.letters + action })
}

这是我们链接它们的方式:

handle(messageStream,initialState)

这是编写用于多人游戏的FRP驱动服务器的正确方法吗?这里的“架构”正确吗?是否有避免MessageStream方法,还是这样做的正确方法handle中的递归似乎有点可疑(像栈一样的感觉可能会变得很大),但是我看不到任何其他避免全局状态的方法

这里另一个令人困惑的部分是,此结构强制按顺序处理所有操作。 什么都不会同时发生。但是,如果处理消息是我想并行化的密集操作,而我只想同步更新状态怎么办?从结构上讲,人们将如何去做呢?

编辑

这里是handle的重写,更像是reduce

const reduce = async (
  stream: MessageStream<Action>,callbackfn: (
    state: State,action: Action
  ) => { newState: State; sideEffects: SideEffect[] },initialState: State,executeSideEffect: (sideEffect: SideEffect) => void
) => {
  let state = initialState
  while (true) {
    const action = await stream.pop()
    const { newState,sideEffects } = callbackfn(state,action)
    sideEffects.map(executeSideEffect)
    state = newState
  }
}

// example usage
reduce(
  messageStream,(s,a) => ({
    newState: { letters: s.letters + a.addLetter },sideEffects: [
      {
        type: SideEffectType.NotifyUser,info: `Got your message,${a.addLetter}!`,},],}),{ letters: "a" },(e) => console.log(e)
)

然后,在socket.on("message")中,将动作推至messageStream,就像上面一样。这样,所有非纯行为都包含在reduce函数的顶层。但是,一种潜在的反模式是reduce从不返回任何内容。那不好吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...