代码之家  ›  专栏  ›  技术社区  ›  sdgfsdh

我该怎么说。使用异步转换函数进行收集?

  •  2
  • sdgfsdh  · 技术社区  · 6 年前

    假设我有两个 async 功能:

    • fetchCategories 获取产品类别的列表( string List )
    • fetchProductsForCategory 获取给定类别的产品列表( 字符串列表 )

    我想写一个函数 fetchProducts 获取所有类别的所有产品。结果应该是一个元组列表( string * string List ).

    然而,我不确定现在是否适合 异步的 Seq.collect 在一起

    以下是我的尝试,希望能让我的意图更加清晰:

    let fetchProducts () = async {
      let! categories = fetchCategories ()
      return categories
        |> Seq.collect (fun c -> async {
          let! products = fetchProductsForCategory c
          return products
            |> Seq.map fun p -> (c, p)
        })
        |> Seq.toList
    }
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   Fyodor Soikin    6 年前

    实现你所追求的目标最直接的方法就是简单地运行所有 fetchProductsForCategory 一个接一个地,然后连接他们的结果。要在运行下一个执行之前等待上一个执行完成,请使用 Async.RunSynchronously :

    let fetchProducts () = async {
      let! categories = fetchCategories ()
      return categories
        |> Seq.collect (fun c ->
          fetchProductsForCategory c 
            |> Async.RunSynchronously          
            |> Seq.map (fun p -> (c, p))
        )
        |> Seq.toList
    }
    

    (顺便说一句,请注意,您的代码不会生成 Seq<string * string list> 你说你期待,但是 Seq<string * string> -每种产品及其类别;但这不是重点)

    然而,这种方法有一个明显的缺点,那就是浪费宝贵的时间。处决 获取产品类别 可以并行运行,从而获得更好的性能。

    罗:有一个应用程序可以实现这一点。这个 Async.Parallel 函数接受一系列异步计算,并行运行它们,并将其结果作为数组返回:

    let fetchProducts () = async {
      let! categories = fetchCategories ()
      let! products = categories 
                       |> Seq.map fetchProductsForCategory 
                       |> Async.Parallel
    
      Seq.zip categories products
    }