从寓言中返回异步值

Bre*_*rry 0 f# fable-f# elmish

这是一个客户端Fable.Remoting示例,它打印异步函数的结果。

    // Client code (Compiled to Javascript using Fable)
    // ============
    open Fable.Remoting.Client

    let server = Proxy.create<IServer>

    async {
     let! length = server.getLength “hello”
     do printfn “%d” length // 5
    }
    |> Async.StartImmediate
Run Code Online (Sandbox Code Playgroud)

我如何获得length价值?

rmu*_*unn 5

我看到您已经用标记了您的问题,所以我假设您已Msg定义类型。不要使用Async.StartImmediateAsync.RunSynchronously; 在Elmish中,Cmd.OfAsync一旦异步块返回一个值,就应该使用它来调度要调度的消息。有在四个功能Cmd.OfAsync(和相同的四个出现在Cmd.OfPromise如孔): ,eitherperformattemptresult。我将为您分解它们,因为它们的文档还不够完善:

  • either:有四个参数,taskargofSuccess,和ofErrortask是您要调用的异步函数(类型为'a -> Async<'b>)。arg'a要传递给task函数的类型的参数。ofSuccess是一种类型的函数'b -> 'Msg:它将接收异步函数的结果并应创建一条消息,大概是一条包含'b结果的消息。最后,ofError是一个函数类型exn -> 'Msg:如果该task函数引发异常,ofError则将调用而不是ofSuccess,并且应该将该异常转换为代码可以处理的Elmish消息(可能是将错误记录到Javascript控制台的消息)或通过Thoth.Toast弹出通知 或类似的东西)。
  • perform:喜欢,either但没有ofError参数。如果您的async命令无法失败(远程API调用永远不会发生这种情况,因为网络断开或服务器无响应的情况很可能发生),或者您只是不在乎异常并且不介意使用引发未处理的异常。
  • attempt:像,either但没有ofSuccess参数,因此如果task函数成功,该函数的结果将被忽略。
  • result:这是完全不同的。它只需要一个类型的参数Async<'Msg>,即,您将async已经传递给它的块传递给它。

使用您编写的代码,Cmd.OfAsync.result如果您想对代码进行最少的更改,就可以使用,但是我建议您Cmd.OfAsync.perform改用(并Cmd.OfAsync.either在编写一些错误处理代码后将其升级到)。我将向您展示两种方式:

type Msg =
    // ... rest of your messages go here
    | GetLength of string
    | LengthResult of int

let update msg model =
    match msg with
    // ... rest of your update function
    | GetLength s ->
        let usePerform = true
        if usePerform then
            model, Cmd.OfAsync.perform server.getLength s LengthResult
        else
            let length : Async<Msg> = async {
                let! length = server.getLength s
                return (LengthResult length)
            }
            model, Cmd.OfAsync.result length
    | LengthResult len ->
        // Do whatever you needed to do with the API result
        printfn "Length was %d" len
        model, Cmd.none
Run Code Online (Sandbox Code Playgroud)

如果您正在使用either(一旦投入生产,您实际上应该这样做),那么将LogError of exn处理第三条消息,例如:

    | LogError e ->
        printfn "Error: %s" e.Message
        model, Cmd.none
Run Code Online (Sandbox Code Playgroud)

Cmd.OfAsync.perform在代码线之上将成为:

        model, Cmd.OfAsync.either server.getLength s LengthResult LogError
Run Code Online (Sandbox Code Playgroud)

这是在Elmish中处理异步生成功能的正确方法。