async-await - F# 中的嵌套异步上下文

标签 async-await f#

我必须通过网络多次调用 API。

let RestCall1 args = async{ Thread.Sleep (1000); return args}
let RestCall2 args = async{Thread.Sleep (1000); return args} 

我知道 async{...} 上下文会影响性能,因此我尝试最大程度地减少创建的上下文数量。另外,管道化也很尴尬。

let nested4 args = async{ let! x = RestCall1 args; return args }
let nested7 args = async{ let! x = RestCall2 args; return args }

let outerAsync (args : string) =
    async {
        let args1 = args
                    |> nested1
                    |> nested2
                    |> nested3
        let! args2 = nested4 args1
        let args3 = args2
                    |> nested5
                    |> nested6
        return nested7 args3          
    }

有没有办法在不使用 RunSynch 阻塞线程的情况下执行此操作(如下面的示例)?

let nested4 args = RestCall1 args |> Async.RunSynchronously
let nested7 args = RestCall2 args |> Async.RunSynchronously

let outerAsync (args : string) =
    async {
        return
            args
            |> nested1
            |> nested2
            |> nested3
            |> nested4
            |> nested5
            |> nested6
            |> nested7 
    }

最佳答案

您想要避免 Async.Runsynchronously 是正确的,这会阻塞(请参阅 "Does Async.RunSynchronously block?" )。

正如 TheQuickBrownFox 所建议的,您需要一个提供 Async.map 和 Async.bind 的库。这里我使用了FsToolkit.ErrorHandling:

  open System.Threading
  open FsToolkit.ErrorHandling

  let restCall1 args = async{ Thread.Sleep (1000); return args }
  let restCall2 args = async{ Thread.Sleep (1000); return args }

  let nested1 args = args
  let nested2 args = args
  let nested3 args = args
  let nested4 args = restCall1 args
  let nested5 args = args
  let nested6 args = args
  let nested7 args = restCall2 args

  let outerAsync (args : string) : Async<string> =
    args
    |> nested1
    |> nested2
    |> nested3
    |> nested4
    |> Async.map nested5
    |> Async.map nested6
    |> Async.bind nested7

Async.map 采用nested5 并将其签名从 (string -> string) 更改为至(Async<string> -> Async<string>) 。它被称为 functor .

Async.bind 采用nested7 并将其签名从 (string -> Async<string>) 更改为至(Async<string> -> Async<string>) .

关于async-await - F# 中的嵌套异步上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64811512/

相关文章:

f# - 在计算表达式中争论 TryWith

compilation - F#:如何在测试项目中避免 "[FS0988] Main module of program is empty: nothing will happen when it is run"?

c# - MonoDevelop 的 System.TypeLoadException

c# - 使用和不使用异步的任务返回类型

JavaScript:异步取消 ondragstart

.net - 如何处理一批任务中的部分成功?

c# - 即发即弃方法

asynchronous - 如何确保 Async.StartChild 在继续之前已启动?

F# 代码执行顺序

javascript - Try/catch block 破坏了异步 JS 代码