延迟Tokio流

时间:2017-09-30 12:18:27

标签: stream rust rust-tokio

给定Stream,我想创建一个新的Stream,其中元素的产生时间延迟。

我尝试编写使用tokio_core::reactor::Timeoutand_then Stream extern crate tokio_core; extern crate futures; use std::time::Duration; use futures::{Future, Stream, stream, Sink}; use self::futures::sync::{mpsc}; use tokio_core::reactor; const NUM_ITEMS: u32 = 8; fn main() { let mut core = reactor::Core::new().unwrap(); let handle = core.handle(); let chandle = handle.clone(); let (sink, stream) = mpsc::channel::<u32>(0); let send_stream = stream::iter_ok(0 .. NUM_ITEMS) .and_then(move |i: u32| { let cchandle = chandle.clone(); println!("Creating a timeout object..."); reactor::Timeout::new(Duration::new(1,0), &cchandle) .map_err(|_| ()) .and_then(|_| Ok(i)) }); let sink = sink.sink_map_err(|_| ()); handle.spawn(sink.send_all(send_stream).and_then(|_| Ok(()))); let mut incoming_items = Vec::new(); { let keep_messages = stream.for_each(|item| { incoming_items.push(item); println!("item = {}", item); Ok(()) }); core.run(keep_messages).unwrap(); } assert_eq!(incoming_items, (0 .. NUM_ITEMS).collect::<Vec<u32>>()); } 组合的代码,但延迟不起作用:我立即获得所有元素,没有延迟。

这是一个自包含的示例(playground):

Creating a timeout object...
Creating a timeout object...
item = 0
Creating a timeout object...
item = 1
Creating a timeout object...
item = 2
Creating a timeout object...
item = 3
Creating a timeout object...
item = 4
Creating a timeout object...
item = 5
Creating a timeout object...
item = 6
item = 7

为了完整性,这是我得到的输出:

reactor::Timeout::new(Duration::new(1,0), &cchandle)
    .map_err(|_| ())
    .and_then(|_| Ok(i))

我怀疑问题出在以下几个方面:

Timeout

虽然我不确定如何解决这个问题,但我可能并没有真正等待返回的{{1}}对象。

1 个答案:

答案 0 :(得分:1)

我怀疑,问题在于新创建的and_then的操纵(使用Timeout)。我们要么首先打开调用reactor::Timeout::new的结果,如果手动完成,可能会变得混乱,或者使用into_future将结果转换为Future,然后使用它使用Future组合器。

解决问题的代码:

extern crate tokio_core;
extern crate futures;

use std::time::Duration;

use futures::{Future, Stream, stream, Sink, IntoFuture};
use self::futures::sync::{mpsc};
use tokio_core::reactor;

const NUM_ITEMS: u32 = 8;

fn main() {
    let mut core = reactor::Core::new().unwrap();
    let handle = core.handle();
    let chandle = handle.clone();

    let (sink, stream) = mpsc::channel::<u32>(0);

    let send_stream = stream::iter_ok(0 .. NUM_ITEMS)
        .and_then(move |i: u32| {
                  let cchandle = chandle.clone();
                  println!("Creating a timeout object...");
                  reactor::Timeout::new(Duration::new(1,0), &cchandle)
                      .into_future()
                      .and_then(move |timeout| timeout.and_then(move |_| Ok(i)))
                      .map_err(|_| ())
        });

    let sink = sink.sink_map_err(|_| ());
    handle.spawn(sink.send_all(send_stream).and_then(|_| Ok(())));

    let mut incoming_items = Vec::new();
    {
        let keep_messages = stream.for_each(|item| {
            incoming_items.push(item);
            println!("item = {}", item);
            Ok(())
        });

        core.run(keep_messages).unwrap();
    }
    assert_eq!(incoming_items, (0 .. NUM_ITEMS).collect::<Vec<u32>>());
}

请注意,正在使用两个and_then。第一个解包从调用Result获得的reactor::Timeout::new。第二个实际上等待Timeout开火。