问题描述
这是一个较大项目的一部分,我在其中重写了多人游戏的命令性代码以使其正常运行。现在,我或多或少地是从一开始就试图从高层次思考结构。这就是我的想法:
弥合命令功能鸿沟的部分是此类:
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 (将#修改为@)