简体   繁体   English

长时间运行的进程在React + Redux应用程序中的位置在哪里?

[英]Where do long-running processes live in a React + Redux application?

Where should long running processes "live" in a react+redux app? 长期运行的流程应该在react + redux应用程序中“活动”?

For a simple example, consider a class which sends and receives messages over a websocket: 举一个简单的例子,考虑一个通过websocket发送和接收消息的类:

class WebsocketStreamer {
  sendMessage(message) {
    this.socket.send(…);
  }

  onMessageReceive(event) {
    this.dispatch({
        type: "STREAMER_RECV",
        message: event.data,
    })
  }
}

How should the lifecycle of this class be managed? 如何管理这个类的生命周期?

My first instinct is to keep it on the store : 我的第一直觉是把它放在store

var stores = {
  streamer: function(state={}, action) {
    if (action.type == "@@INIT")
      return { streamer: new WebsocketStreamer() }
    if (action.type == "STREAMER_SEND")
      state.streamer.sendMessage(action.message)
    return state;
  }
}

But, aside from being a bit strange, there's also no way for the WebsocketStreamer to get access to the dispatch() function, and it breaks hot reloading. 但是,除了有点奇怪之外, WebsocketStreamer也无法访问dispatch()函数,并且它会破坏热重新加载。

Another potential solution is to keep it in a global somewhere: 另一个可能的解决方案是将其保持在某个地方:

const streamer = new WebsocketStreamer();

But that has obvious testability implications, and breaks hot reloading too. 但这具有明显的可测试性含义,并且也打破了热重新加载。

So, where should a long running process live in a react + redux app? 那么,一个长期运行的进程应该放在react + redux应用程序中?

Note: I realize that this simple example could be built with just stores + action providers. 注意:我意识到这个简单的例子可以只使用商店+动作提供者构建。 But I would specifically like to know where long-lived processes should exist in situations where they exist. 但我特别想知道在它们存在的情况下应该存在长期存在的过程。

In my experience, there are two options. 根据我的经验,有两种选择。 First, you can pass store to any non-Redux code and dispatch actions from here. 首先,您可以将商店传递给任何非Redux代码并从此处调度操作。 I've did this with socket connection and all was fine. 我用套接字连接做了这个,一切都很好。 Second, if you need socket or whatever to change with redux actions, it looks like a good idea to put connection and it's management in custom middleware. 其次,如果你需要套接字或者用redux动作改变什么,那么将连接和它的管理放在自定义中间件中似乎是一个好主意。 You'll have access to store API as well as will be informed on all actions dispatching, so could do anything you need to. 您将可以访问商店API,并将获得所有调度操作的通知,因此可以执行您需要的任何操作。

I'm doing something similar with websockets. 我正在做与websockets类似的事情。 In my case, I simply wrap the websocket client in a React component that renders null and inject it as close to the root as possible. 在我的例子中,我只是将websocket客户端包装在一个呈现null的React组件中,并尽可能靠近root注入它。

<App>
    <WebSocketClientThingy handlers={configuredHandlers}/>
    ....
</App>

Here's a quick example. 这是一个简单的例子。 It's pretty naive, but get's stuff done. 这很天真,但是完成了。

https://github.com/trbngr/react-example-pusher https://github.com/trbngr/react-example-pusher

Quick note: The websocket doesn't live in the store. 快速说明:websocket不在商店中。 It's simply there and publishes actions. 它就在那里并发布行动。

EDIT: I decided to explore setting the client (long-lived object) into the global state. 编辑:我决定探索将客户端(长期存在的对象)设置为全局状态。 I gotta say that I'm a fan of this approach. 我得说我是这种方法的粉丝。

https://github.com/trbngr/react-example-pusher/tree/client_as_state https://github.com/trbngr/react-example-pusher/tree/client_as_state

I opensource a demo issue tracker with long running ops using React/Redux/Node,all the involved code but is open sourced and MIT. 我使用React / Redux / Node打开了一个带有长时间运行操作的演示问题跟踪器,所有涉及的代码都是开源的和MIT。 Sometimes I need to pull or push the repo and depending on the connection this might take a long time, this is where the next long running operation comes in. 有时我需要拉动或推动回购,并且根据连接这可能需要很长时间,这是下一个长时间运行操作的地方。

Overall the key points of the approach are: 总体而言,该方法的关键点是:

  • A redux store with the active operations and its status. 具有活动操作及其状态的redux存储。
  • A redux store with events of the operations 具有操作事件的redux商店
  • Initialize the operations store with all the ongoing operations during the page initialization 在页面初始化期间使用所有正在进行的操作初始化操作存储
  • Use a http events server to update a operation status, either data, error, complete, progress, etc. 使用http事件服务器更新操作状态,包括数据,错误,完成,进度等。
  • Connect the components like buttons to the ongoing operation status. 将按钮等组件连接到正在进行的操作状态。
  • For each component keep a list of involved operations and parameters, if the operation and parameter match... change the button state to loading/done/etc.. 对于每个组件,保留一个涉及的操作和参数的列表,如果操作和参数匹配...将按钮状态更改为加载/完成/等。
  • Change the status of the operation store with the events update or request results (I am using a GraphQL and all the mutations returns a "Operation" type) 使用事件更新或请求结果更改操作存储的状态(我使用的是GraphQL,所有突变都返回“操作”类型)

The involved repositories are: 涉及的存储库是:

This is how it looks like running: https://user-images.githubusercontent.com/36018976/60389724-4e0aa280-9ac7-11e9-9129-b8e31b455c50.gif 这就是它的运行方式: https//user-images.githubusercontent.com/36018976/60389724-4e0aa280-9ac7-11e9-9129-b8e31b455c50.gif

Keeping the state this way also helps you to: 以这种方式保持状态也有助于您:

  • The ongoing operations state is keep even if the window is refreshed 即使刷新窗口,也会保持正在进行的操作状态
  • If you open two or more windows and perform operations in one window, the state of the running operations and UI for all the windows are sync as well. 如果打开两个或多个窗口并在一个窗口中执行操作,则所有窗口的运行操作和UI的状态也是同步的。

I hope the approach or code helps. 我希望方法或代码有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM