F# Make Async<Async<MyTpe>[]> 到 Async<MyType>[]
F# Make Async<Async<MyTpe>[]> to Async<MyType>[]
我从 HTTP
调用中获得了一些数据列表。然后我知道要为另一个 HTTP
调用获取什么值。我想让一切都是异步的。但我需要将此数据与 Expecto
's testCaseAsync : string -> Async<unit> -> Test
一起使用。所以,我的目标是获得这样的签名 Async<Item>[]
所以,我想获得 testCaseAsync
.
的列表
所以,我基本上是这样的:
// Async<Async<Item>[]>
let getAsyncCalls =
async {
let! table = API.getTable ()
// Async<Item>[]
let items =
table.root
|> Array.map (fun x -> API.getItem x.id)
return item
}
如果我运行他们并行我得到:
// Async<Item[]>
let getAsyncCalls =
async {
let! table = API.getTable ()
// Item[]
let! items =
table.root
|> Array.map (fun x -> API.getItem x.id)
return item
}
所以,这并没有让我达到 Async<Item>[]
。我不确定这是否可能。我想避免 Async.RunSynchronously
用于 API.getTable
调用,因为这会导致死锁,对吧?它很可能会从缓存值 (memoized
) 中调用,所以我不确定这会有所作为。
我想我会继续努力,除非有人比我更聪明:-)提前致谢!
一般来说,你不能把Async<Async<T>[]>
变成Async<T>[]
。问题是即使要获取数组的长度,也需要异步执行一些操作,所以没有办法在异步之外 "lift" 数组。如果你事先知道数组的长度,那么你就可以做到这一点。
下面的函数将 Async<'T[]>
变成 Async<'T>[]
,前提是你给它数组的长度。如您所知,返回的异步需要以某种方式共享对一个顶级异步的访问。我能想到的最简单的方法是使用任务。为您的用例调整它应该很容易:
let unwrapAsyncArray (asyncs:Async<'T[]>) len =
let task = asyncs |> Async.StartAsTask
Array.init len (fun i -> async {
let! res = Async.AwaitTask task
if res.Length <> len then failwith "Wrong length!"
return res.[i] }
)
我从 HTTP
调用中获得了一些数据列表。然后我知道要为另一个 HTTP
调用获取什么值。我想让一切都是异步的。但我需要将此数据与 Expecto
's testCaseAsync : string -> Async<unit> -> Test
一起使用。所以,我的目标是获得这样的签名 Async<Item>[]
所以,我想获得 testCaseAsync
.
所以,我基本上是这样的:
// Async<Async<Item>[]>
let getAsyncCalls =
async {
let! table = API.getTable ()
// Async<Item>[]
let items =
table.root
|> Array.map (fun x -> API.getItem x.id)
return item
}
如果我运行他们并行我得到:
// Async<Item[]>
let getAsyncCalls =
async {
let! table = API.getTable ()
// Item[]
let! items =
table.root
|> Array.map (fun x -> API.getItem x.id)
return item
}
所以,这并没有让我达到 Async<Item>[]
。我不确定这是否可能。我想避免 Async.RunSynchronously
用于 API.getTable
调用,因为这会导致死锁,对吧?它很可能会从缓存值 (memoized
) 中调用,所以我不确定这会有所作为。
我想我会继续努力,除非有人比我更聪明:-)提前致谢!
一般来说,你不能把Async<Async<T>[]>
变成Async<T>[]
。问题是即使要获取数组的长度,也需要异步执行一些操作,所以没有办法在异步之外 "lift" 数组。如果你事先知道数组的长度,那么你就可以做到这一点。
下面的函数将 Async<'T[]>
变成 Async<'T>[]
,前提是你给它数组的长度。如您所知,返回的异步需要以某种方式共享对一个顶级异步的访问。我能想到的最简单的方法是使用任务。为您的用例调整它应该很容易:
let unwrapAsyncArray (asyncs:Async<'T[]>) len =
let task = asyncs |> Async.StartAsTask
Array.init len (fun i -> async {
let! res = Async.AwaitTask task
if res.Length <> len then failwith "Wrong length!"
return res.[i] }
)