我是F#的新手,对于从C#开发人员的角度理解F#中的异步操作感到困惑。比如以下C#代码片段:
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
如何用F#写同样的代码?
我是F#的新手,对于从C#开发人员的角度理解F#中的异步操作感到困惑。比如以下C#代码片段:
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string content = await response.Content.ReadAsStringAsync();
如何用F#写同样的代码?
这里有一个函数,应该可以实现你所需的功能(请注意,你需要将代码放在异步计算表达式中,以便使用let!语法):
let getAsync (url:string) =
async {
let httpClient = new System.Net.Http.HttpClient()
let! response = httpClient.GetAsync(url) |> Async.AwaitTask
response.EnsureSuccessStatusCode () |> ignore
let! content = response.Content.ReadAsStringAsync() |> Async.AwaitTask
return content
}
SqlConnection
和执行 SqlCommand
。 - pimHttpClient
编写 F# 封装 - 例如对于相同概念保持相同的命名等。我会进行编辑以反映这一点。 - Ruben Bartelinkasync
: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
}
我个人的看法是,当使用EnsureSuccessStatusCode()
时,我们应该处理HttpRequestException
异常。
下面是一个模块的开头,它包装了HttpClient
,将URL的响应缓冲为一个string
,并安全地封装在Result<'a,'b>
中,以提高容错性。
注:Original Answer翻译成"最初的回答"
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.FusionTasks
,您就可以拥有清晰的语法,无需像|> 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
}
let
应该改为use
,因为httpClient
和response
都是可释放资源(IDisposable)。 - CogwheelHttpClient
在这方面是有特殊性的。 - psfinaki