我有一个使用OpenAPI Generator生成的(云)API的可用的Rust示例.

API表示资源(应用程序-服务-部署)的层次 struct ,因此函数的实现必须是嵌套的;代码需要迭代每个应用程序以获取应用程序的服务,然后迭代服务...

我无法将接口调用合并到async fn‘S,至少有两个原因:

  1. 加入期货市场
  2. 收集错误

我希望定义3个具有公共返回类型的函数;每个函数都有不同的参数:

async fn fetch_and_transform_apps() -> Result<Vec<Foo>, anyhow::Error> {...}
async fn fetch_and_transform_services() -> Result<Vec<Foo>, anyhow::Error> {...}
async fn fetch_and_transform_deployments() -> Result<Vec<Foo>, anyhow::Error> {...}

我想不出如何实现上面的#1和#2(#3正在工作).这就是我所拥有的:

async fn fetch_and_transform_services(...) -> Result<vec<Foo>, anyhow::Error> {
    let list_services_reply = list_services(...).await?;
    let services = list_services_reply
        .services.ok_or_else(|| anyhow::anyhow!("No services found"))?;

    let items_futures = services
        .iter()
        .map(|service| async move {
            let items: Result<Vec<Foo>, Error> = fetch_and_transform_deployments(...).await;
            items
        });
    let items = join_all(items_futures)
        .await
        // The type here is: Vec<Result<Vec<Foo>, anyhow::Error>>
        .into_iter()
        // The collect type results in the error
        .collect::<Result<Vec<koyeb::Koyeb>, anyhow::Error>>();

    items
}

错误:

不能从对类型为std::vec::Vec<Foo>的元素的迭代器生成类型为std::vec::Vec<Foo>的值 特性FromIterator<std::vec::Vec<Foo>>不是针对std::vec::Vec<Foo>实现的,这是Result<std::vec::Vec<Foo>, anyhow::Error>: FromIterator<Result<std::vec::Vec<Foo>, anyhow::Error>>所需的 特征FromIterator<Foo>是针对std::vec::Vec<Foo>实现的 对于该特征的实现,预期为Foo,结果为std::vec::Vec<Foo> Result<std::vec::Vec<Foo>, anyhow::Error>实施FromIterator<Result<std::vec::Vec<Foo>, anyhow::Error>>所需

推荐答案

我不认为collect有这个能力,但你可以用try_fold来代替.

fn collect_result_vecs<Iter, Item, E>(iter: Iter) -> Result<Vec<Item>, E>
where
    Iter: IntoIterator<Item = Result<Vec<Item>, E>>,
{
    iter.into_iter().try_fold(Vec::new(), |mut v, item| {
        v.extend(item?);
        Ok(v)
    })
}

您将在此处使用此函数:

let items = collect_result_vecs(join_all(items_futures).await);

如果外部Vec有许多物品(>;Vec0),您可能希望在等待之间构建Vec,这样您就不会在较长时间内阻塞.

use futures::stream::FuturesOrdered;
let items_futures = FuturesOrdered::from_iter(items_futures);
let mut items = Vec::new();
while let Some(next_vec) = items_futures.next().await {
    items.extend(next_vec?);
}
Ok(items)

这也将在一个失败时立即取消未完成的期货,而不是运行每一个完成,但如果你需要完成它们,你可以完成items_futures,而不是返回next_vec?.

Rust相关问答推荐

如何从polars DataFrame中获取一个列作为Option String?<>

为什么我需要在这个代码示例中使用&

当Option为None时,Option数组是否占用Rust中的内存?

展开枚举变量并返回所属值或引用

下载压缩文件

使用Box优化可选的已知长度数组的内存分配

为什么 js_sys Promise::new 需要 FnMut?

如何正确使用git2::Remote::push?

在 Rust 中查找向量中 dyn struct 的索引

我可以用 Rust 编写一个不可变变量

如何在 Rust 中将 Vec> 转换为 Vec>?

Rust 中的方法调用有什么区别?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

是否可以预测堆栈溢出?

Rust 中函数的类型同义词

如果我不想运行析构函数,如何移出具有析构函数的 struct ?

TinyVec 如何与 Vec 大小相同?

编写 TOML 文件以反序列化为 struct 中的枚举

如何用另一个变量向量置换 rust simd 向量?

基于名称是否存在的条件编译