问题描述
我想这是一个经典的 C# 到 F# 转换,我还没有完全理解。
https://playwright.dev/dotnet/docs/intro
C# 代码是
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync();
var page = await browser.NewPageAsync();
await page.GotoAsync("http://www.bing.com");
await page.ScreenshotAsync(path: outputFile);
我已经开始了,但已经有点迷失了。
let playwright: Playwright = PlaywrightSharp.Playwright.CreateAsync() |> Async.AwaitTask
类型不正确。我在这里做错了什么?
Error FS0001 This expression was expected to have type
'Playwright'
but here has type
'Async<IPlaywright>'
解决方法
您可以使用 TaskBuilder 框架 https://github.com/rspeele/TaskBuilder.fs
dotnet 添加包 Taskbuilder.fs
写
task {
use! playwright = Playwright.CreateAsync()
let! browser = playwright.Chromium.LaunchAsync()
let! page = browser.NewPageAsync()
let! response = page.GoToAsync("http://www.bing.com")
let! title = page.GetTitleAsync()
printfn "%s" title
}
|> Task.WaitAll
,
一种方法是使用 F# 对 async computation expressions 的内置支持。翻译看起来像这样:
let (~~) = Async.AwaitTask
async {
use! playwright = ~~Playwright.CreateAsync()
let! browser = ~~playwright.Chromium.LaunchAsync()
let! page = ~~browser.NewPageAsync()
do! ~~page.GoToAsync("http://www.slashdot.com") |> Async.Ignore
do! ~~page.ScreenshotAsync(outputFile) |> Async.Ignore
} |> Async.RunSynchronously
这里有一些你需要知道的微妙之处:
- F# 有自己的异步类型,称为
Async<'T>
。我已经使用Async.AwaitTask
从 C# 样式的任务转换而来,并定义了一个前缀运算符~~
,使其看起来更简洁。 - F# 不支持
DisposeAsync
计算表达式 yet 中的async
,因此浏览器无法正确处理。如果需要,您可以在块的末尾添加do! browser.DisposeAsync().AsTask() |> Async.AwaitTask
以手动执行此操作。 - F# 要求我们明确忽略不需要的返回值,我已经通过
Async.Ignore
做到了这一点。