如何从F#使用HttpClient?

如何从F#使用HttpClient?,f#,task-parallel-library,async-await,dotnet-httpclient,c#-to-f#,F#,Task Parallel Library,Async Await,Dotnet Httpclient,C# To F#,我是F#新手,从C#开发人员的角度理解F#中的异步。假设用C#编写以下代码片段: var-httpClient=new-httpClient(); var response=wait-httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); string content=wait response.content.ReadAsStringAsync(); 如何在F#?中编写相同的代码您可以使用async: let readStr

我是F#新手,从C#开发人员的角度理解F#中的异步。假设用C#编写以下代码片段:

var-httpClient=new-httpClient();
var response=wait-httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content=wait response.content.ReadAsStringAsync();

如何在F#?

中编写相同的代码您可以使用
async

let readString (url: Uri) = async {
    let httpClient = new HttpClient();
    let! response = httpClient.GetAsync(url) |> Async.AwaitTask
    response.EnsureSuccessStatusCode() |> ignore
    return! response.Content.ReadAsStringAsync() |> Async.AwaitTask
}

下面是一个函数,它应该完成您想要的功能(请注意,为了使用let!语法,您必须将代码包装在异步计算表达式中):


如果您使用F#中的
HttpClient
,您至少需要阅读并了解中的已建立模式

[见评论]TL;博士正如@pimbrouwers所指出的,应该注意的是,您不必再使用它——在您的上下文中对自己的助手集进行细分和/或改进可以使您获得更合适的抽象(并在学习过程中为您带来好处)


说到这一点:在F#中,将很少使用和/或过于特定的助手放在非中心位置被认为是惯用做法。

只要我的两分钱。但我的理解是,在使用
EnsureSuccessStatusCode()
时,我们应该处理
HttpRequestException

下面是模块包装
HttpClient
的开始,该模块将URL响应缓冲到
字符串中,并安全地包装到
结果中,以提高容错性

module Http =
    open System    
    open System.Net.Http

    let getStringAsync url =
        async {
            let httpClient = new HttpClient() 
            // This can be easily be made into a HttpClientFactory.Create() call
            // if you're using >= netcore2.1

            try 
                use! resp = httpClient.GetAsync(Uri(url), HttpCompletionOption.ResponseHeadersRead) |> Async.AwaitTask                       
                resp.EnsureSuccessStatusCode |> ignore

                let! str = resp.Content.ReadAsStringAsync() |> Async.AwaitTask
                return Ok str
            with
            | :? HttpRequestException as ex -> return ex.Message |> Error
        }

只需使用
FSharp.Control.fusiontask
,就可以获得清晰的语法,而不必像这样使用
|>Async.AwaitTask

   let httpClient = new System.Net.Http.HttpClient ()

   let getAsync (url:string) = 
    async {
        let! response = httpClient.GetAsync url
        response.EnsureSuccessStatusCode () |> ignore
        let! content = response.Content.ReadAsStringAsync ()
        return content
    }

前两个
不应该让
s成为
使用
s吗?(httpClient&响应为IDisposable)可能没有,
httpClient
并非故意不尊重。但我发现答案是,有人直接去图书馆是一种逃避。当然,你最终可能会不可避免地使用它。但在我看来,你应该先亲自去那里。否则,我们最终会遇到一群程序员,他们已经远离他们真正想要做的事情,他们只能使用外部库来完成他们的工作。ADO.NET就是一个很好的例子。我所做的.NET开发人员中有多少人对代理
SqlConnection
和执行
SqlCommand
一无所知,你会感到震惊。关键是,你自己先试试。犯错误把事情搞砸了(我知道我总是这样)。但实际上在这个过程中我学到了一些东西;今天我不会写同样的答案。然而,我的观点是,在没有意识到一个广泛使用的库的情况下,不要为
HttpClient
编写F#wrapping,例如,为相同的概念使用相同的命名等。将进行编辑以反映这一点。
   let httpClient = new System.Net.Http.HttpClient ()

   let getAsync (url:string) = 
    async {
        let! response = httpClient.GetAsync url
        response.EnsureSuccessStatusCode () |> ignore
        let! content = response.Content.ReadAsStringAsync ()
        return content
    }