如何使用异步转换函数进行Seq.collect?

时间:2018-06-01 19:39:04

标签: f# async-await

假设我有两个async函数:

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

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

但是,我现在不确定asyncSeq.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 个答案:

答案 0 :(得分:4)

实现你所追求的最直接的方法是一个接一个地连续运行所有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>,但fetchProductsForCategory - 每个产品都有其类别;但这不是重点“

然而,这种方法有一个明显的缺点,就是浪费宝贵的时间。 let fetchProducts () = async { let! categories = fetchCategories () let! products = categories |> Seq.map fetchProductsForCategory |> Async.Parallel Seq.zip categories products } 的执行可以并行运行,从而实现更好的性能。

而且:有一个应用程序。 Async.Parallel函数采用一系列异步计算,并行运行它们,并将结果作为数组返回:

subdir/.htaccess