首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Fable.Remoting返回异步值

从Fable.Remoting返回异步值
EN

Stack Overflow用户
提问于 2019-08-23 04:26:16
回答 3查看 845关注 0票数 5

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

代码语言:javascript
复制
    // 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

如何获得length值?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-23 06:29:32

我看到你用埃尔米什标记了你的问题,所以我假设你定义了一个Msg类型。不要使用Async.StartImmediateAsync.RunSynchronously;在Elmish中,当异步块返回值时,您应该使用Cmd.OfAsync来调度要发送的消息。Cmd.OfAsync中有四个函数(在Cmd.OfPromise中也有相同的四个):eitherperformattemptresult。我会帮你把它们分解一下,因为它们的文档还不足以让人窒息:

  • either:接受四个参数,taskargofSuccessofErrortask是您想要调用的异步函数(类型为'a -> Async<'b>)。arg是要传递给task函数的'a类型的参数。ofSuccess是一个'b -> 'Msg类型的函数:它将接收异步函数的结果,并且应该创建一条消息,可能是一条合并了'b结果的消息。最后,ofError是一个类型为exn -> 'Msg的函数:如果task函数抛出一个异常,那么将调用ofError而不是ofSuccess,并将该异常转换为您的代码可以处理的Elmish消息(可能会将错误记录到Javascript控制台或弹出带有Thoth.Toast之类的通知)。
  • perform:像either一样,但是没有ofError参数。如果您的异步命令不能失败(远程API调用永远不会发生这种情况,因为网络关闭或服务器没有响应),或者您只是不关心异常,并且不介意抛出未处理的异常,就使用此方法。
  • attempt:与either类似,但是没有ofSuccess参数,因此如果task函数成功,它的结果将被忽略。
  • result:这个完全不同。它只需要一个Async<'Msg>类型的参数,即传递给它一个已经产生消息的async块。

对于您编写的代码,如果希望对代码进行最小的更改,可以使用Cmd.OfAsync.result,但我建议使用Cmd.OfAsync.perform (并在编写了一些错误处理代码后将其升级到Cmd.OfAsync.either )。我会教你两种方法:

代码语言:javascript
复制
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

如果您使用的是either (一旦投入生产,您确实应该这么做),那么第三条消息LogError of exn将被处理如下:

代码语言:javascript
复制
    | LogError e ->
        printfn "Error: %s" e.Message
        model, Cmd.none

上面代码中的Cmd.OfAsync.perform行将变成:

代码语言:javascript
复制
        model, Cmd.OfAsync.either server.getLength s LengthResult LogError

这是处理Elmish中异步生成函数的正确方法。

票数 15
EN

Stack Overflow用户

发布于 2019-08-23 05:15:27

异步是在return中使用F#的地方之一。所以您需要返回长度值。此外,Async.StartImmediate还返回() (单元)。如果需要提取值,可以使用其他方法,例如Async.RunSynchronously。取决于你需要用它实现什么。

代码语言:javascript
复制
let length = 
    async {
         let! length = async {return String.length "hello"}
         do printfn "%d" length // 5
         return length
        } |> Async.RunSynchronously

length // val it : int = 5

顺便说一句你说的是寓言。因此,您可能可以使用JS promise

F#中有关异步的一些资源:

喷气机F#异步指南

异步编程

FSharp的乐趣和利润

Microsoft

C#和F#异步

票数 4
EN

Stack Overflow用户

发布于 2020-12-28 11:27:18

对于那些想从js代码调用的人。

代码语言:javascript
复制
// Client code (Compiled to Javascript using Fable)
// ============
open Fable.Remoting.Client
open Fable.Core // required for Async.StartAsPromise 


let server = Proxy.create<IServer>
let len_from_fable () = 
    async {
         let! length = server.getLength “hello”
         return length
    } |> Async.StartAsPromise

来自js的电话

代码语言:javascript
复制
    async func() {
        let len = await len_from_fable()
        print(len)
    }

作品于寓言3.0。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57619894

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档