我是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
}
如果你在F#中使用Http.fs做任何事情,你至少应该阅读并了解HttpClient
中已建立的模式。
[见评论] TL; DR ... but Beware the Share。正如@pimbrouwers所指出的,应该注意的是,你不一定要使用它 - 在你的上下文中对你自己的帮助器进行子集化和/或演化可以使你获得更好的拟合抽象(并带给你的好处)在途中的学习)。
到目前为止:在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
}
只是我的两分钱。但我的理解是,在使用HttpRequestException
时我们应该处理EnsureSuccessStatusCode()
。
下面是一个包装HttpClient
的模块的开始,它将缓冲URL响应到string
并安全地换行Result<'a, 'b>
以提高容错能力。
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