1

最佳实践是在一个地方“注册”http客户端,以便可以从这个Elmish更新功能中重用它?而不必为每个请求创建它。

let update message model =
    match message with
    | SetMessage s -> { model with x = s }
    | Loading -> { model with x = "Doing something long ..." }

let handleClick model dispatch _ = 
    dispatch Loading
    async {
        let url = Uri "https://api.github.com"
        -- FIXME: too expensive to do this on per-update basis
        use httpClient = new HttpClient(BaseAddress = url)
        let! resp = httpClient.GetAsync "/users/srid" |> Async.AwaitTask
        let! s = resp.Content.ReadAsStringAsync() |> Async.AwaitTask
        dispatch (SetMessage s)
    } |> Async.Start

我觉得这通常会出现在 Startup.fs 中。我使用仅限客户端的 Bolero Web 应用程序,因此如下所示:

 builder.Services.AddSingleton<HttpClient>(new HttpClient (BaseAddress=apiBase))

但是问题就变成了......我如何从我的 F# 程序中访问它?什么是惯用方式?

4

1 回答 1

1

可能最好的方法是将 HttpClient 添加为模型中的另一个字段或作为更新函数的另一个参数。

let update (client:HttpClient) message model = // Your code

let url = Uri "https://api.github.com"
let httpClient = new HttpClient(BaseAddress = url)

一般来说,您不应该在您的视图中“做工作”,并且通过扩展,事件处理程序。相反,您应该使用 Elmish Cmd 模块,如下所示:

let update httpClient message model =
    match message with
    | SetMessage s -> 
        { model with x = s }, Cmd.none
    | GetMessageAsync -> 
        let cmd = 
            let getHttp () = 
                async {
                    let! resp = httpClient.GetAsync "/users/srid" |> Async.AwaitTask
                    return! resp.Content.ReadAsStringAsync() |> Async.AwaitTask
                }
            Cmd.OfAsync.perform getHttp () (fun s -> SetMessage s)

        { model with x = "Doing something long ..." }, cmd

let handleClick model dispatch _ = 
    dispatch GetMessageAsync
于 2021-03-24T01:57:50.960 回答