F# SAFE 如何处理消息 DU 变体的增长?

F# SAFE how to deal with growth of message DU variants?

在 F# SAFE 堆栈中有一个 DU 类型,它定义了在服务器和客户端之间流动的所有类型的消息。在示例应用程序中,有 <10 个,我查看了提供的示例 - 所有这些都没有很多可能的类型。但是如果应用程序不小怎么办——DU 中会有数百种类型;这将变得难以维护。所以我决定把这个类型分成子类型,把逻辑放在相应的文件中。

这是我的简化类型:

 type Msg2 =
    | LoginMsg of LoginState
    | RegisterMsg of RegisterState
    | ViewUpdateMsg of ViewUpdateState

登录状态在另一个文件中定义:

 type LoginState =
        | Login
        | LogInResult of LoginResult

登录模块与登录一起工作:

let workWithLogin (model: Model) (msg: LoginState) (todosApi: ITodosApi) : Model * Cmd<LoginState> =
    match msg with
    | LoginState.Login ->
        let result =
            Cmd.OfAsync.perform todosApi.login model.InputData LoginState.LogInResult

        model, result
    | LoginState.LogInResult data ->
        { model with
              LoginState = getVal data.Message
              Token = data.Token },
        Cmd.none

注意它 returns Model * Cmd<LoginState>.

现在我需要修复我的更新功能:

let update2 (msg: Msg2) (model: Model) : Model * Cmd<Msg2> =
     match msg with
     | LoginMsg n ->
         let ret = workWithLogin model n todosApi
         model, snd ret
     | RegisterMsg n -> ...
     | ViewUpdateMsg n ->  ...

这里的问题是我从登录模块获取 Cmd<LoginState> 并且需要以某种方式将其转换为 Cmd<Msg2> 所以我要么需要创建新的 Msg2 类型,要么将 DU 变体 LoginMsg of LoginState 转换为 Msg2。我不明白如何从 Cmd<LoginState>.

获取 LogInResult 数据

我该如何解决这个问题?大项目中消息类型多的问题是如何解决的?

您在“子”消息中所做的包装是正确的方法,您可能应该对模型做同样的事情 - 即让 Login 拥有自己的模型。要在不同的 Cmd<'msg> 之间转换,有一个 Cmd.map。在您的情况下,您可以:

let update2 (msg: Msg2) (model: Model) : Model * Cmd<Msg2> =
  match msg with
  | LoginMsg n ->
      let (loginModel, loginCmd) = workWithLogin model n todosApi
      { model with Login = loginModel }, Cmd.map LoginMsg loginCmd

您可以在此处查看 Cmd 的一些 API 描述:https://elmish.github.io/elmish/cmd.html