如何使用 Elmish 调试器解决编码器问题?

How do I solve encoder problem with the Elmish Debugger?

我有一个使用 websockets 在 SAFE-Stack 中构建的应用程序,或多或少遵循这里的方法:https://github.com/CompositionalIT/safe-sockets

它工作正常,但 Elmish 调试器不喜欢此示例中的 WsSender 类型:


type ConnectionState =
        | DisconnectedFromServer
        | ConnectedToServer of WsSender
        | Connecting

        member this.IsConnected =
            match this with
            | ConnectedToServer _ -> true
            | DisconnectedFromServer | Connecting -> false

    and WsSender = Msg -> Unit

在浏览器控制台中给出以下错误消息:

谁能告诉我如何解决这个问题? (假设它是可以修复的并且我已经正确诊断出问题。)谢谢。

您看到此错误是因为 Elmish.Debugger 使用 Thoth.Json 将您的 Msg/Model 序列化为 JSON 格式。

类型 WsSender 不能用 JSON 格式表示,因为它是一个函数。所以 Thoth.Json 要求你解释它应该如何编码这种类型。

您可以通过创建所谓的 extraCoder 来做到这一点:

在你的情况下,你将不得不创建一个假的 encoder/decoder "just" 来让调试器满意。

module CustomEncoders =

    let wsSenderEncoder (_ : WsSender) = Encode.string "WsSender function"

    let wsSenderDecoder = Decode.fail "Decoding is not supported for WsSender type"

    let myExtraCoders =
        Extra.empty
        |> Extra.withCustom wsSenderEncoder wsSenderDecoder 


    let modelEncoder = Encode.Auto.generateEncoder(extra = myExtraCoders)
    let modelDecoder = Decode.Auto.generateDecoder(extra = myExtraCoders)

在您的程序创建中,您应该将 Program.withDebugger 替换为 Program.withDebuggerCoders 并为其提供您创建的编码器和解码器。

Program.withDebuggerCoders CustomEncoders.modelEncoder CustomEncoders.modelDecoder

我尝试了一些尝试,想出一些可以在需要时更容易拥有多个额外编码器的东西。这似乎有效 - 认为它可能对其他人有帮助。


module CustomEncoders =

    let inline addDummyCoder<'b> extrasIn =
        let typeName = string typeof<'b>
        let simpleEncoder(_ : 'b) = Encode.string (sprintf "%s function" typeName)
        let simpleDecoder = Decode.fail (sprintf "Decoding is not supported for %s type" typeName)
        extrasIn |> Extra.withCustom simpleEncoder simpleDecoder

    let inline buildExtras<'a> extraCoders =
        let myEncoder:Encoder<'a> = Encode.Auto.generateEncoder(extra = extraCoders)
        let myDecoder:Decoder<'a> = Decode.Auto.generateDecoder(extra = extraCoders)
        (myEncoder, myDecoder)

type TestType = Msg -> Unit
type TestType2 = string -> Unit

let extras = Extra.empty
                |> CustomEncoders.addDummyCoder<TestType>
                |> CustomEncoders.addDummyCoder<TestType2>
                |> CustomEncoders.buildExtras<Model.Model>


#if DEBUG
open Elmish.Debug
open Elmish.HMR
#endif


Program.mkProgram Model.init Model.update View.render
|> Program.withSubscription subs 
#if DEBUG
|> Program.withConsoleTrace
#endif
|> Program.withReactBatched "elmish-app"
#if DEBUG
|> Program.withDebuggerCoders (fst extras) (snd extras)
#endif
|> Program.run


如果有人对如何操作有更好的想法,我很乐意根据他们的建议更新此答案。此外,泛型类型中的撇号似乎打乱了上面的代码美化器——我需要做些什么来解决这个问题吗?