我是否必须使用 Immutable JS 忽略全局模块状态的概念?

Do I have to ignore the concept of global module state with Immutable JS?

我刚刚偶然发现了 Immutable JS,我认为它看起来是一个非常有趣的库,可以减少由于程序员 error/accidental 突变导致错误的可能性以及它提供的性能优化,但是我正在努力了解如何跟踪模块内的状态。

例如,如果我有一个 socket.io 服务器 运行 支持多个流,我通常会在该模块的全局上下文中有两个变量来跟踪连接的客户端和当前可用的流:

var clients = []
var streams = []

如果用户要连接,我可以简单地在 socket ios io.on("connection") 事件侦听器中使用 .push 我可以放心,我的客户端状态现在将包含新加入的套接字。

在 Immutable JS 中,我有一个模块的全局对象,现在看起来像:

var state = Immutable.Map({
    clients : Immutable.List.of(),
    streams : Immutable.List.of()
})

在 socket io 的连接处理程序内部,如何更新全局状态?我相信 Immutable JS 是这样工作的,所以维护应用程序状态似乎是不可能的(因为我目前正在考虑它的方式)

// Define the Immutable array, this remains constant throughout the application
var state = Immutable.Map({
    clients : Immutable.List.of(),
    streams : Immutable.List.of()
})

io.on("connection", (socket) => {

     console.log(state.clients)    

     // I would like to update the state of clients here, but I believe that 
     // I am only able to make a local copy within the context of the current
     // scope, I would then lose access to this on the next socket joining?

     var clientsArray = state.clients
     clientsArray.push(socket)
     state.set("clients", clientsArray)

     console.log(state.clients)
})

根据我的理解,我相信 console.log 语句在两个连接的客户端上会产生以下输出:

// First client connects
[]
[ { socket object } ]

// Second client connects
[]
[ { socket object } ]

我是否可以更新对象以便我得到

[ { socket object }, { socket object } ]

还是我需要坚持使用全局可变状态?我问这个问题的唯一原因是,当我过去使用 React 时,您可以在方法中更新组件状态,然后在组件的其他地方使用该新状态。

您的代码缺少一个简单的赋值。当您使用不可变时,任何更新操作(如 set)都会导致创建一个全新的对象。在您的情况下,以下代码 state.set("clients", clientsArray) 不会更改全局状态,但会 returns 一个具有修改后的 clients 列表的新实例。 要解决此问题,您只需使用调用结果更新全局状态,就像这样 -

state = state.set("clients", clientsArray);

或者您可以一次性重写所有内容 -

state = state.set("clients", state.get("clients").push(socket));

希望对您有所帮助!

根据经验,请记住,每当调用 changes/mutates 不可变方法时,您始终需要进行赋值。