asynchronous - 异步方法中的类型不匹配
问题描述
我正在编写一个异步方法,它应该异步查询端口,直到找到一个端口,或者在 5 分钟后超时;
member this.GetPort(): Async<Port> = this._GetPort(DateTime.Now)
member this._GetPort(startTime: DateTime): Async<Port> = async {
match this._TryGetOpenPort() with
| Some(port) -> port
| None -> do
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
else
do! Async.Sleep(100)
let! result = this._GetPort(startTime)
result}
member this._TryGetOpenPort(): Option<Port> =
// etc.
但是,我在 ; 中遇到了一些奇怪的类型不一致_GetPort
。该函数说我正在返回一个类型Async<unit>
而不是Async<Port>
.
解决方案
这有点不直观,但让你的代码工作的方法是这样的:
member private this.GetPort(startTime: DateTime) =
async {
match this.TryGetOpenPort() with
| Some port ->
return port
| None ->
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
do! Async.Sleep(100)
let! result = this.GetPort(startTime)
return result
}
member private this.TryGetOpenPort() = failwith "yeet" // TODO
我冒昧地清理了一些东西并将成员设为私有,因为这似乎是您在这里主要追求的内容,并以更详细的内部方式获取端口。
您的代码未编译的原因是因为您return
从计算中得到的内容不一致:
- 如果
Some(port)
您缺少return
关键字 - 需要将值提升回Async<port>
- 你
if
提出异常的表达式有一个else
分支,但你不是return
来自两者。在这种情况下,由于您显然不希望返回任何内容而只是引发异常,因此您可以省略else
并使其成为命令式程序流,就像在非异步代码中一样。
您可能希望考虑的另一件事是如果抛出异常是您想要的,或者只是返回一个Result<T,Err>
或一个选项是正确的调用。异常本质上并不坏,但如果有一种很好的方法可以将含义赋予包装返回值的类型,那么很多 F# 编程通常会导致避免使用它们。
推荐阅读
- php - 在 PHP 中执行 SQLite SELECT 和 UPDATE 时出现 504 网关超时
- javascript - 护照Js:重定向到另一个带有数据的网址
- c - 第一列中的用户输入值,第二列中显示多维数组的正方形
- python-3.x - 如何以原始顺序获取字典的键
- android - 在 Activity 或 Fragment 之外获取 ViewModel 实例的正确方法
- java - 使用 instanceof 扩展 java.util.Date 的掩码对象返回 true
- python - 类型错误:需要整数参数
- reactjs - 堆栈中嵌套抽屉时不显示屏幕标题
- sqlite - 使用 Xamarin.Forms 从 Sqlite 数据库中获取数据
- asp.net - 如何使用 ASP.NET 在解决方案中存储图像?