如何从FuturesUnordered返回错误?

时间:2019-05-13 09:37:37

标签: rust rust-tokio

我有一组并行运行的期货,如果一个期货失败,我希望得到错误返回给调用者。

这是我到目前为止一直在测试的内容:

use futures::prelude::*;
use futures::stream::futures_unordered::FuturesUnordered;
use futures::{future, Future};

fn main() {
    let tasks: FuturesUnordered<_> = (1..10).map(|_| async_func(false)).collect();

    let mut runtime = tokio::runtime::Runtime::new().expect("Unable to start runtime");
    let res = runtime.block_on(tasks.into_future());

    if let Err(_) = res {
        println!("err");
    }
}

fn async_func(success: bool) -> impl Future<Item = (), Error = String> {
    if success {
        future::ok(())
    } else {
        future::err("Error".to_string())
    }
}

如何从任何失败的期货中获取错误?更好的是,如果单个期货失败,则停止运行任何未决的期货。

1 个答案:

答案 0 :(得分:1)

您的代码已经 返回并处理了错误。如果您尝试使用该错误,编译器将迅速将您引导至解决方案:

if let Err(e) = res {
    println!("err: {}", e);
}
error[E0277]: `(std::string::String, futures::stream::futures_unordered::FuturesUnordered<impl futures::future::Future>)` doesn't implement `std::fmt::Display`
  --> src/main.rs:12:29
   |
12 |         println!("err: {}", e);
   |                             ^ `(std::string::String, futures::stream::futures_unordered::FuturesUnordered<impl futures::future::Future>)` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `(std::string::String, futures::stream::futures_unordered::FuturesUnordered<impl futures::future::Future>)`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: required by `std::fmt::Display::fmt`

Err值是您的错误的元组,原始流将在您处理错误后继续提取。 Stream::into_future / StreamFuture就是这样。

访问元组中的第一个值以获取错误:

if let Err((e, _)) = res {
    println!("err: {}", e);
}

如果要查看所有值,则可以不断地对流进行轮询(但不要这样做,因为它可能效率不高):

let mut f = tasks.into_future();
loop {
    match runtime.block_on(f) {
        Ok((None, _)) => {
            println!("Stream complete");
            break;
        }
        Ok((Some(v), next)) => {
            println!("Success: {:?}", v);
            f = next.into_future();
        }
        Err((e, next)) => {
            println!("Error: {:?}", e);
            f = next.into_future();
        }
    }
}