我有一长串希望使用Stream::buffer_unordered
/ Stream::buffered
运行的期货。我将此流与for_each
合并为一个单独的future,然后使用Tokio对其全部执行。期货之一返回错误是很常见的。根据文档,for_each
将在返回错误时停止。
返回这些错误后如何忽略或仅打印一条消息,并继续执行后续期货?
以下是与我的情况类似的通用代码:
use futures::stream;
use futures::stream::Stream;
use futures::future::err;
use futures::future::ok;
use tokio;
fn main() {
let queries: Vec<u32> = (0..10).collect();
let futures = queries.into_iter().map(move |num| {
println!("Started {}", num);
// Maybe throw error
let future = match num % 3 {
0 => ok::<u32, u32>(num),
_ => err::<u32, u32>(num)
};
future
});
let stream = stream::iter_ok(futures);
let num_workers = 8;
let future = stream
.buffer_unordered(num_workers)
.map_err(|err| {
println!("Error on {:?}", err);
})
.for_each(|n| {
println!("Success on {:?}", n);
Ok(())
});
tokio::runtime::run(future);
}
如果您尝试此示例,则抛出Err
时,期货队列将尽早停止执行。
答案 0 :(得分:2)
Stream::map_err
-提供错误值,它可以转换类型,但将其保留为错误。
Stream::or_else
-带有错误值,它可以将错误转换为成功,而使成功值保持不变。
Stream::then
-提供成功值和错误值,并且可以做您想做的任何事情。
Stream::map
不能让您将错误转化为成功,所以它没有用。 Stream::or_else
确实提供功能,但是当您可以将错误类型转换为成功类型时使用。只有Stream::then
使您能够一次转换两种类型。
Stream::flatten
可用于将一个流转换为单个流。
使用Result
可被视为迭代器的事实将其组合起来,您可以创建以下代码:
stream
.then(|r| future::ok(stream::iter_ok::<_, ()>(r)))
.flatten()
无论流的项目是Ok
还是Err
,我们都将其转换为迭代器并从中创建流。然后,我们将数据流弄平。
如果您想打印出错误,我会使用Stream::inspect_err
:
stream.inspect_err(|err| println!("Error on {:?}", err))
完整代码:
use futures::{
future,
stream::{self, Stream},
}; // 0.1.25;
use tokio; // 0.1.14
fn main() {
let stream = stream::iter_ok({
(0..10).map(|num| {
println!("Started {}", num);
match num % 3 {
0 => future::ok(num),
_ => future::err(num),
}
})
})
.buffer_unordered(2);
let stream = stream
.inspect_err(|err| println!("Error on {:?}", err))
.then(|r| future::ok(stream::iter_ok::<_, ()>(r)))
.flatten();
tokio::run({
stream.for_each(|n| {
println!("Success on {:?}", n);
Ok(())
})
});
}
Started 0
Started 1
Success on 0
Started 2
Error on 1
Started 3
Error on 2
Started 4
Success on 3
Started 5
Error on 4
Started 6
Error on 5
Started 7
Success on 6
Started 8
Error on 7
Started 9
Error on 8
Success on 9